From patchwork Fri Jan 13 06:23:21 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christoph Hellwig X-Patchwork-Id: 642862 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id F296FC54EBE for ; Fri, 13 Jan 2023 06:25:50 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S237909AbjAMGZo (ORCPT ); Fri, 13 Jan 2023 01:25:44 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:33442 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S239005AbjAMGYb (ORCPT ); Fri, 13 Jan 2023 01:24:31 -0500 Received: from bombadil.infradead.org (bombadil.infradead.org [IPv6:2607:7c80:54:3::133]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id F1E0669B33; Thu, 12 Jan 2023 22:24:11 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=infradead.org; s=bombadil.20210309; h=Content-Transfer-Encoding: MIME-Version:References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From:Sender :Reply-To:Content-Type:Content-ID:Content-Description; bh=YWdaNZZD6eiGGHiQwqB4d/n7vbdllZAZ4PVlQ9KrUog=; b=XtPGvVCciAHH/ZLi442ryHF6rq FvgKnRpeqvwCx9UPgqvxyoSez2P7/TsQH4CCdKmAVKMjtEs7KN5fhRpLHTjMdmTb4fMzzf6CmNKlf rXdbPlEScIlBvjJrEpLQ9Qz+cT5QX9vrjKWKFTMLmEzur4VlSN6Xl4jhStM3ZSCwOvwfNkCRTuNnR wJyIbeNnp1Bzl3/RFdCiY+e0gUrTlrvJFtmxx0gpbmv+sIP/JUZGEtJIDk593yDFSk9RClQJfmg7Y 4kjnLNtrXGl9NJsEFRSHVUmWUakVHMHmyXzQxjKYElq0QLSA3Qcs/NoVXvf4FXw2zlWkEQ7IFJk43 R2e+Go7Q==; Received: from [2001:4bb8:181:656b:9509:7d20:8d39:f895] (helo=localhost) by bombadil.infradead.org with esmtpsa (Exim 4.94.2 #2 (Red Hat Linux)) id 1pGDTr-000lRy-FI; Fri, 13 Jan 2023 06:24:00 +0000 From: Christoph Hellwig To: Yoshinori Sato , Rich Felker , Arnd Bergmann , Greg Kroah-Hartman Cc: Laurent Pinchart , Kieran Bingham , Geert Uytterhoeven , linux-kernel@vger.kernel.org, linux-watchdog@vger.kernel.org, devicetree@vger.kernel.org, linux-arch@vger.kernel.org, dmaengine@vger.kernel.org, dri-devel@lists.freedesktop.org, linux-renesas-soc@vger.kernel.org, linux-i2c@vger.kernel.org, linux-input@vger.kernel.org, linux-media@vger.kernel.org, linux-mmc@vger.kernel.org, linux-mtd@lists.infradead.org, netdev@vger.kernel.org, linux-gpio@vger.kernel.org, linux-rtc@vger.kernel.org, linux-spi@vger.kernel.org, linux-serial@vger.kernel.org, linux-usb@vger.kernel.org, linux-fbdev@vger.kernel.org, alsa-devel@alsa-project.org, linux-sh@vger.kernel.org Subject: [PATCH 04/22] sound: remove sound/sh Date: Fri, 13 Jan 2023 07:23:21 +0100 Message-Id: <20230113062339.1909087-5-hch@lst.de> X-Mailer: git-send-email 2.39.0 In-Reply-To: <20230113062339.1909087-1-hch@lst.de> References: <20230113062339.1909087-1-hch@lst.de> MIME-Version: 1.0 X-SRS-Rewrite: SMTP reverse-path rewritten from by bombadil.infradead.org. See http://www.infradead.org/rpr.html Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org Now that arch/sh is removed these drivers are dead code. Signed-off-by: Christoph Hellwig --- sound/Kconfig | 2 - sound/Makefile | 2 +- sound/sh/Kconfig | 32 -- sound/sh/Makefile | 11 - sound/sh/aica.c | 628 ---------------------------------------- sound/sh/aica.h | 68 ----- sound/sh/sh_dac_audio.c | 412 -------------------------- 7 files changed, 1 insertion(+), 1154 deletions(-) delete mode 100644 sound/sh/Kconfig delete mode 100644 sound/sh/Makefile delete mode 100644 sound/sh/aica.c delete mode 100644 sound/sh/aica.h delete mode 100644 sound/sh/sh_dac_audio.c diff --git a/sound/Kconfig b/sound/Kconfig index e56d96d2b11cae..14361bb428baa1 100644 --- a/sound/Kconfig +++ b/sound/Kconfig @@ -75,8 +75,6 @@ source "sound/spi/Kconfig" source "sound/mips/Kconfig" -source "sound/sh/Kconfig" - # the following will depend on the order of config. # here assuming USB is defined before ALSA source "sound/usb/Kconfig" diff --git a/sound/Makefile b/sound/Makefile index 04ef04b1168f39..bb4b8806321c67 100644 --- a/sound/Makefile +++ b/sound/Makefile @@ -4,7 +4,7 @@ obj-$(CONFIG_SOUND) += soundcore.o obj-$(CONFIG_DMASOUND) += oss/dmasound/ -obj-$(CONFIG_SND) += core/ i2c/ drivers/ isa/ pci/ ppc/ arm/ sh/ synth/ usb/ \ +obj-$(CONFIG_SND) += core/ i2c/ drivers/ isa/ pci/ ppc/ arm/ synth/ usb/ \ firewire/ sparc/ spi/ parisc/ pcmcia/ mips/ soc/ atmel/ hda/ x86/ xen/ \ virtio/ obj-$(CONFIG_SND_AOA) += aoa/ diff --git a/sound/sh/Kconfig b/sound/sh/Kconfig deleted file mode 100644 index b75fbb3236a7b9..00000000000000 --- a/sound/sh/Kconfig +++ /dev/null @@ -1,32 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-only -# ALSA SH drivers - -menuconfig SND_SUPERH - bool "SUPERH sound devices" - depends on SUPERH - default y - help - Support for sound devices specific to SUPERH architectures. - Drivers that are implemented on ASoC can be found in - "ALSA for SoC audio support" section. - -if SND_SUPERH - -config SND_AICA - tristate "Dreamcast Yamaha AICA sound" - depends on SH_DREAMCAST - select SND_PCM - select G2_DMA - help - ALSA Sound driver for the SEGA Dreamcast console. - -config SND_SH_DAC_AUDIO - tristate "SuperH DAC audio support" - depends on SND - depends on CPU_SH3 && HIGH_RES_TIMERS - select SND_PCM - help - Say Y here to include support for the on-chip DAC. - -endif # SND_SUPERH - diff --git a/sound/sh/Makefile b/sound/sh/Makefile deleted file mode 100644 index c0bbc500c17c73..00000000000000 --- a/sound/sh/Makefile +++ /dev/null @@ -1,11 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-only -# -# Makefile for ALSA -# - -snd-aica-objs := aica.o -snd-sh_dac_audio-objs := sh_dac_audio.o - -# Toplevel Module Dependency -obj-$(CONFIG_SND_AICA) += snd-aica.o -obj-$(CONFIG_SND_SH_DAC_AUDIO) += snd-sh_dac_audio.o diff --git a/sound/sh/aica.c b/sound/sh/aica.c deleted file mode 100644 index 6e9d6bd67369af..00000000000000 --- a/sound/sh/aica.c +++ /dev/null @@ -1,628 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* -* -* Copyright Adrian McMenamin 2005, 2006, 2007 -* -* Requires firmware (BSD licenced) available from: -* http://linuxdc.cvs.sourceforge.net/linuxdc/linux-sh-dc/sound/oss/aica/firmware/ -* or the maintainer -*/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "aica.h" - -MODULE_AUTHOR("Adrian McMenamin "); -MODULE_DESCRIPTION("Dreamcast AICA sound (pcm) driver"); -MODULE_LICENSE("GPL"); -MODULE_FIRMWARE("aica_firmware.bin"); - -/* module parameters */ -#define CARD_NAME "AICA" -static int index = -1; -static char *id; -static bool enable = 1; -module_param(index, int, 0444); -MODULE_PARM_DESC(index, "Index value for " CARD_NAME " soundcard."); -module_param(id, charp, 0444); -MODULE_PARM_DESC(id, "ID string for " CARD_NAME " soundcard."); -module_param(enable, bool, 0644); -MODULE_PARM_DESC(enable, "Enable " CARD_NAME " soundcard."); - -/* Simple platform device */ -static struct platform_device *pd; -static struct resource aica_memory_space[2] = { - { - .name = "AICA ARM CONTROL", - .start = ARM_RESET_REGISTER, - .flags = IORESOURCE_MEM, - .end = ARM_RESET_REGISTER + 3, - }, - { - .name = "AICA Sound RAM", - .start = SPU_MEMORY_BASE, - .flags = IORESOURCE_MEM, - .end = SPU_MEMORY_BASE + 0x200000 - 1, - }, -}; - -/* SPU specific functions */ -/* spu_write_wait - wait for G2-SH FIFO to clear */ -static void spu_write_wait(void) -{ - int time_count; - time_count = 0; - while (1) { - if (!(readl(G2_FIFO) & 0x11)) - break; - /* To ensure hardware failure doesn't wedge kernel */ - time_count++; - if (time_count > 0x10000) { - snd_printk - ("WARNING: G2 FIFO appears to be blocked.\n"); - break; - } - } -} - -/* spu_memset - write to memory in SPU address space */ -static void spu_memset(u32 toi, u32 what, int length) -{ - int i; - unsigned long flags; - if (snd_BUG_ON(length % 4)) - return; - for (i = 0; i < length; i++) { - if (!(i % 8)) - spu_write_wait(); - local_irq_save(flags); - writel(what, toi + SPU_MEMORY_BASE); - local_irq_restore(flags); - toi++; - } -} - -/* spu_memload - write to SPU address space */ -static void spu_memload(u32 toi, const void *from, int length) -{ - unsigned long flags; - const u32 *froml = from; - u32 __iomem *to = (u32 __iomem *) (SPU_MEMORY_BASE + toi); - int i; - u32 val; - length = DIV_ROUND_UP(length, 4); - spu_write_wait(); - for (i = 0; i < length; i++) { - if (!(i % 8)) - spu_write_wait(); - val = *froml; - local_irq_save(flags); - writel(val, to); - local_irq_restore(flags); - froml++; - to++; - } -} - -/* spu_disable - set spu registers to stop sound output */ -static void spu_disable(void) -{ - int i; - unsigned long flags; - u32 regval; - spu_write_wait(); - regval = readl(ARM_RESET_REGISTER); - regval |= 1; - spu_write_wait(); - local_irq_save(flags); - writel(regval, ARM_RESET_REGISTER); - local_irq_restore(flags); - for (i = 0; i < 64; i++) { - spu_write_wait(); - regval = readl(SPU_REGISTER_BASE + (i * 0x80)); - regval = (regval & ~0x4000) | 0x8000; - spu_write_wait(); - local_irq_save(flags); - writel(regval, SPU_REGISTER_BASE + (i * 0x80)); - local_irq_restore(flags); - } -} - -/* spu_enable - set spu registers to enable sound output */ -static void spu_enable(void) -{ - unsigned long flags; - u32 regval = readl(ARM_RESET_REGISTER); - regval &= ~1; - spu_write_wait(); - local_irq_save(flags); - writel(regval, ARM_RESET_REGISTER); - local_irq_restore(flags); -} - -/* - * Halt the sound processor, clear the memory, - * load some default ARM7 code, and then restart ARM7 -*/ -static void spu_reset(void) -{ - unsigned long flags; - spu_disable(); - spu_memset(0, 0, 0x200000 / 4); - /* Put ARM7 in endless loop */ - local_irq_save(flags); - __raw_writel(0xea000002, SPU_MEMORY_BASE); - local_irq_restore(flags); - spu_enable(); -} - -/* aica_chn_start - write to spu to start playback */ -static void aica_chn_start(void) -{ - unsigned long flags; - spu_write_wait(); - local_irq_save(flags); - writel(AICA_CMD_KICK | AICA_CMD_START, (u32 *) AICA_CONTROL_POINT); - local_irq_restore(flags); -} - -/* aica_chn_halt - write to spu to halt playback */ -static void aica_chn_halt(void) -{ - unsigned long flags; - spu_write_wait(); - local_irq_save(flags); - writel(AICA_CMD_KICK | AICA_CMD_STOP, (u32 *) AICA_CONTROL_POINT); - local_irq_restore(flags); -} - -/* ALSA code below */ -static const struct snd_pcm_hardware snd_pcm_aica_playback_hw = { - .info = (SNDRV_PCM_INFO_NONINTERLEAVED), - .formats = - (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_IMA_ADPCM), - .rates = SNDRV_PCM_RATE_8000_48000, - .rate_min = 8000, - .rate_max = 48000, - .channels_min = 1, - .channels_max = 2, - .buffer_bytes_max = AICA_BUFFER_SIZE, - .period_bytes_min = AICA_PERIOD_SIZE, - .period_bytes_max = AICA_PERIOD_SIZE, - .periods_min = AICA_PERIOD_NUMBER, - .periods_max = AICA_PERIOD_NUMBER, -}; - -static int aica_dma_transfer(int channels, int buffer_size, - struct snd_pcm_substream *substream) -{ - int q, err, period_offset; - struct snd_card_aica *dreamcastcard; - struct snd_pcm_runtime *runtime; - unsigned long flags; - err = 0; - dreamcastcard = substream->pcm->private_data; - period_offset = dreamcastcard->clicks; - period_offset %= (AICA_PERIOD_NUMBER / channels); - runtime = substream->runtime; - for (q = 0; q < channels; q++) { - local_irq_save(flags); - err = dma_xfer(AICA_DMA_CHANNEL, - (unsigned long) (runtime->dma_area + - (AICA_BUFFER_SIZE * q) / - channels + - AICA_PERIOD_SIZE * - period_offset), - AICA_CHANNEL0_OFFSET + q * CHANNEL_OFFSET + - AICA_PERIOD_SIZE * period_offset, - buffer_size / channels, AICA_DMA_MODE); - if (unlikely(err < 0)) { - local_irq_restore(flags); - break; - } - dma_wait_for_completion(AICA_DMA_CHANNEL); - local_irq_restore(flags); - } - return err; -} - -static void startup_aica(struct snd_card_aica *dreamcastcard) -{ - spu_memload(AICA_CHANNEL0_CONTROL_OFFSET, - dreamcastcard->channel, sizeof(struct aica_channel)); - aica_chn_start(); -} - -static void run_spu_dma(struct work_struct *work) -{ - int buffer_size; - struct snd_pcm_runtime *runtime; - struct snd_card_aica *dreamcastcard; - dreamcastcard = - container_of(work, struct snd_card_aica, spu_dma_work); - runtime = dreamcastcard->substream->runtime; - if (unlikely(dreamcastcard->dma_check == 0)) { - buffer_size = - frames_to_bytes(runtime, runtime->buffer_size); - if (runtime->channels > 1) - dreamcastcard->channel->flags |= 0x01; - aica_dma_transfer(runtime->channels, buffer_size, - dreamcastcard->substream); - startup_aica(dreamcastcard); - dreamcastcard->clicks = - buffer_size / (AICA_PERIOD_SIZE * runtime->channels); - return; - } else { - aica_dma_transfer(runtime->channels, - AICA_PERIOD_SIZE * runtime->channels, - dreamcastcard->substream); - snd_pcm_period_elapsed(dreamcastcard->substream); - dreamcastcard->clicks++; - if (unlikely(dreamcastcard->clicks >= AICA_PERIOD_NUMBER)) - dreamcastcard->clicks %= AICA_PERIOD_NUMBER; - mod_timer(&dreamcastcard->timer, jiffies + 1); - } -} - -static void aica_period_elapsed(struct timer_list *t) -{ - struct snd_card_aica *dreamcastcard = from_timer(dreamcastcard, - t, timer); - struct snd_pcm_substream *substream = dreamcastcard->substream; - /*timer function - so cannot sleep */ - int play_period; - struct snd_pcm_runtime *runtime; - runtime = substream->runtime; - dreamcastcard = substream->pcm->private_data; - /* Have we played out an additional period? */ - play_period = - frames_to_bytes(runtime, - readl - (AICA_CONTROL_CHANNEL_SAMPLE_NUMBER)) / - AICA_PERIOD_SIZE; - if (play_period == dreamcastcard->current_period) { - /* reschedule the timer */ - mod_timer(&(dreamcastcard->timer), jiffies + 1); - return; - } - if (runtime->channels > 1) - dreamcastcard->current_period = play_period; - if (unlikely(dreamcastcard->dma_check == 0)) - dreamcastcard->dma_check = 1; - schedule_work(&(dreamcastcard->spu_dma_work)); -} - -static void spu_begin_dma(struct snd_pcm_substream *substream) -{ - struct snd_card_aica *dreamcastcard; - struct snd_pcm_runtime *runtime; - runtime = substream->runtime; - dreamcastcard = substream->pcm->private_data; - /*get the queue to do the work */ - schedule_work(&(dreamcastcard->spu_dma_work)); - mod_timer(&dreamcastcard->timer, jiffies + 4); -} - -static int snd_aicapcm_pcm_open(struct snd_pcm_substream - *substream) -{ - struct snd_pcm_runtime *runtime; - struct aica_channel *channel; - struct snd_card_aica *dreamcastcard; - if (!enable) - return -ENOENT; - dreamcastcard = substream->pcm->private_data; - channel = kmalloc(sizeof(struct aica_channel), GFP_KERNEL); - if (!channel) - return -ENOMEM; - /* set defaults for channel */ - channel->sfmt = SM_8BIT; - channel->cmd = AICA_CMD_START; - channel->vol = dreamcastcard->master_volume; - channel->pan = 0x80; - channel->pos = 0; - channel->flags = 0; /* default to mono */ - dreamcastcard->channel = channel; - runtime = substream->runtime; - runtime->hw = snd_pcm_aica_playback_hw; - spu_enable(); - dreamcastcard->clicks = 0; - dreamcastcard->current_period = 0; - dreamcastcard->dma_check = 0; - return 0; -} - -static int snd_aicapcm_pcm_close(struct snd_pcm_substream - *substream) -{ - struct snd_card_aica *dreamcastcard = substream->pcm->private_data; - flush_work(&(dreamcastcard->spu_dma_work)); - del_timer(&dreamcastcard->timer); - dreamcastcard->substream = NULL; - kfree(dreamcastcard->channel); - spu_disable(); - return 0; -} - -static int snd_aicapcm_pcm_prepare(struct snd_pcm_substream - *substream) -{ - struct snd_card_aica *dreamcastcard = substream->pcm->private_data; - if ((substream->runtime)->format == SNDRV_PCM_FORMAT_S16_LE) - dreamcastcard->channel->sfmt = SM_16BIT; - dreamcastcard->channel->freq = substream->runtime->rate; - dreamcastcard->substream = substream; - return 0; -} - -static int snd_aicapcm_pcm_trigger(struct snd_pcm_substream - *substream, int cmd) -{ - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - spu_begin_dma(substream); - break; - case SNDRV_PCM_TRIGGER_STOP: - aica_chn_halt(); - break; - default: - return -EINVAL; - } - return 0; -} - -static unsigned long snd_aicapcm_pcm_pointer(struct snd_pcm_substream - *substream) -{ - return readl(AICA_CONTROL_CHANNEL_SAMPLE_NUMBER); -} - -static const struct snd_pcm_ops snd_aicapcm_playback_ops = { - .open = snd_aicapcm_pcm_open, - .close = snd_aicapcm_pcm_close, - .prepare = snd_aicapcm_pcm_prepare, - .trigger = snd_aicapcm_pcm_trigger, - .pointer = snd_aicapcm_pcm_pointer, -}; - -/* TO DO: set up to handle more than one pcm instance */ -static int __init snd_aicapcmchip(struct snd_card_aica - *dreamcastcard, int pcm_index) -{ - struct snd_pcm *pcm; - int err; - /* AICA has no capture ability */ - err = - snd_pcm_new(dreamcastcard->card, "AICA PCM", pcm_index, 1, 0, - &pcm); - if (unlikely(err < 0)) - return err; - pcm->private_data = dreamcastcard; - strcpy(pcm->name, "AICA PCM"); - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, - &snd_aicapcm_playback_ops); - /* Allocate the DMA buffers */ - snd_pcm_set_managed_buffer_all(pcm, - SNDRV_DMA_TYPE_CONTINUOUS, - NULL, - AICA_BUFFER_SIZE, - AICA_BUFFER_SIZE); - return 0; -} - -/* Mixer controls */ -#define aica_pcmswitch_info snd_ctl_boolean_mono_info - -static int aica_pcmswitch_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - ucontrol->value.integer.value[0] = 1; /* TO DO: Fix me */ - return 0; -} - -static int aica_pcmswitch_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - if (ucontrol->value.integer.value[0] == 1) - return 0; /* TO DO: Fix me */ - else - aica_chn_halt(); - return 0; -} - -static int aica_pcmvolume_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 1; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 0xFF; - return 0; -} - -static int aica_pcmvolume_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_card_aica *dreamcastcard; - dreamcastcard = kcontrol->private_data; - if (unlikely(!dreamcastcard->channel)) - return -ETXTBSY; /* we've not yet been set up */ - ucontrol->value.integer.value[0] = dreamcastcard->channel->vol; - return 0; -} - -static int aica_pcmvolume_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_card_aica *dreamcastcard; - unsigned int vol; - dreamcastcard = kcontrol->private_data; - if (unlikely(!dreamcastcard->channel)) - return -ETXTBSY; - vol = ucontrol->value.integer.value[0]; - if (vol > 0xff) - return -EINVAL; - if (unlikely(dreamcastcard->channel->vol == vol)) - return 0; - dreamcastcard->channel->vol = ucontrol->value.integer.value[0]; - dreamcastcard->master_volume = ucontrol->value.integer.value[0]; - spu_memload(AICA_CHANNEL0_CONTROL_OFFSET, - dreamcastcard->channel, sizeof(struct aica_channel)); - return 1; -} - -static const struct snd_kcontrol_new snd_aica_pcmswitch_control = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "PCM Playback Switch", - .index = 0, - .info = aica_pcmswitch_info, - .get = aica_pcmswitch_get, - .put = aica_pcmswitch_put -}; - -static const struct snd_kcontrol_new snd_aica_pcmvolume_control = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "PCM Playback Volume", - .index = 0, - .info = aica_pcmvolume_info, - .get = aica_pcmvolume_get, - .put = aica_pcmvolume_put -}; - -static int load_aica_firmware(void) -{ - int err; - const struct firmware *fw_entry; - spu_reset(); - err = request_firmware(&fw_entry, "aica_firmware.bin", &pd->dev); - if (unlikely(err)) - return err; - /* write firmware into memory */ - spu_disable(); - spu_memload(0, fw_entry->data, fw_entry->size); - spu_enable(); - release_firmware(fw_entry); - return err; -} - -static int add_aicamixer_controls(struct snd_card_aica *dreamcastcard) -{ - int err; - err = snd_ctl_add - (dreamcastcard->card, - snd_ctl_new1(&snd_aica_pcmvolume_control, dreamcastcard)); - if (unlikely(err < 0)) - return err; - err = snd_ctl_add - (dreamcastcard->card, - snd_ctl_new1(&snd_aica_pcmswitch_control, dreamcastcard)); - if (unlikely(err < 0)) - return err; - return 0; -} - -static int snd_aica_remove(struct platform_device *devptr) -{ - struct snd_card_aica *dreamcastcard; - dreamcastcard = platform_get_drvdata(devptr); - if (unlikely(!dreamcastcard)) - return -ENODEV; - snd_card_free(dreamcastcard->card); - kfree(dreamcastcard); - return 0; -} - -static int snd_aica_probe(struct platform_device *devptr) -{ - int err; - struct snd_card_aica *dreamcastcard; - dreamcastcard = kzalloc(sizeof(struct snd_card_aica), GFP_KERNEL); - if (unlikely(!dreamcastcard)) - return -ENOMEM; - err = snd_card_new(&devptr->dev, index, SND_AICA_DRIVER, - THIS_MODULE, 0, &dreamcastcard->card); - if (unlikely(err < 0)) { - kfree(dreamcastcard); - return err; - } - strcpy(dreamcastcard->card->driver, "snd_aica"); - strcpy(dreamcastcard->card->shortname, SND_AICA_DRIVER); - strcpy(dreamcastcard->card->longname, - "Yamaha AICA Super Intelligent Sound Processor for SEGA Dreamcast"); - /* Prepare to use the queue */ - INIT_WORK(&(dreamcastcard->spu_dma_work), run_spu_dma); - timer_setup(&dreamcastcard->timer, aica_period_elapsed, 0); - /* Load the PCM 'chip' */ - err = snd_aicapcmchip(dreamcastcard, 0); - if (unlikely(err < 0)) - goto freedreamcast; - /* Add basic controls */ - err = add_aicamixer_controls(dreamcastcard); - if (unlikely(err < 0)) - goto freedreamcast; - /* Register the card with ALSA subsystem */ - err = snd_card_register(dreamcastcard->card); - if (unlikely(err < 0)) - goto freedreamcast; - platform_set_drvdata(devptr, dreamcastcard); - snd_printk - ("ALSA Driver for Yamaha AICA Super Intelligent Sound Processor\n"); - return 0; - freedreamcast: - snd_card_free(dreamcastcard->card); - kfree(dreamcastcard); - return err; -} - -static struct platform_driver snd_aica_driver = { - .probe = snd_aica_probe, - .remove = snd_aica_remove, - .driver = { - .name = SND_AICA_DRIVER, - }, -}; - -static int __init aica_init(void) -{ - int err; - err = platform_driver_register(&snd_aica_driver); - if (unlikely(err < 0)) - return err; - pd = platform_device_register_simple(SND_AICA_DRIVER, -1, - aica_memory_space, 2); - if (IS_ERR(pd)) { - platform_driver_unregister(&snd_aica_driver); - return PTR_ERR(pd); - } - /* Load the firmware */ - return load_aica_firmware(); -} - -static void __exit aica_exit(void) -{ - platform_device_unregister(pd); - platform_driver_unregister(&snd_aica_driver); - /* Kill any sound still playing and reset ARM7 to safe state */ - spu_reset(); -} - -module_init(aica_init); -module_exit(aica_exit); diff --git a/sound/sh/aica.h b/sound/sh/aica.h deleted file mode 100644 index 021b132e088e82..00000000000000 --- a/sound/sh/aica.h +++ /dev/null @@ -1,68 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* aica.h - * Header file for ALSA driver for - * Sega Dreamcast Yamaha AICA sound - * Copyright Adrian McMenamin - * - * 2006 - */ - -/* SPU memory and register constants etc */ -#define G2_FIFO 0xa05f688c -#define SPU_MEMORY_BASE 0xA0800000 -#define ARM_RESET_REGISTER 0xA0702C00 -#define SPU_REGISTER_BASE 0xA0700000 - -/* AICA channels stuff */ -#define AICA_CONTROL_POINT 0xA0810000 -#define AICA_CONTROL_CHANNEL_SAMPLE_NUMBER 0xA0810008 -#define AICA_CHANNEL0_CONTROL_OFFSET 0x10004 - -/* Command values */ -#define AICA_CMD_KICK 0x80000000 -#define AICA_CMD_NONE 0 -#define AICA_CMD_START 1 -#define AICA_CMD_STOP 2 -#define AICA_CMD_VOL 3 - -/* Sound modes */ -#define SM_8BIT 1 -#define SM_16BIT 0 -#define SM_ADPCM 2 - -/* Buffer and period size */ -#define AICA_BUFFER_SIZE 0x8000 -#define AICA_PERIOD_SIZE 0x800 -#define AICA_PERIOD_NUMBER 16 - -#define AICA_CHANNEL0_OFFSET 0x11000 -#define AICA_CHANNEL1_OFFSET 0x21000 -#define CHANNEL_OFFSET 0x10000 - -#define AICA_DMA_CHANNEL 5 -#define AICA_DMA_MODE 5 - -#define SND_AICA_DRIVER "AICA" - -struct aica_channel { - uint32_t cmd; /* Command ID */ - uint32_t pos; /* Sample position */ - uint32_t length; /* Sample length */ - uint32_t freq; /* Frequency */ - uint32_t vol; /* Volume 0-255 */ - uint32_t pan; /* Pan 0-255 */ - uint32_t sfmt; /* Sound format */ - uint32_t flags; /* Bit flags */ -}; - -struct snd_card_aica { - struct work_struct spu_dma_work; - struct snd_card *card; - struct aica_channel *channel; - struct snd_pcm_substream *substream; - int clicks; - int current_period; - struct timer_list timer; - int master_volume; - int dma_check; -}; diff --git a/sound/sh/sh_dac_audio.c b/sound/sh/sh_dac_audio.c deleted file mode 100644 index 8ebd972846acb5..00000000000000 --- a/sound/sh/sh_dac_audio.c +++ /dev/null @@ -1,412 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/* - * sh_dac_audio.c - SuperH DAC audio driver for ALSA - * - * Copyright (c) 2009 by Rafael Ignacio Zurita - * - * Based on sh_dac_audio.c (Copyright (C) 2004, 2005 by Andriy Skulysh) - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -MODULE_AUTHOR("Rafael Ignacio Zurita "); -MODULE_DESCRIPTION("SuperH DAC audio driver"); -MODULE_LICENSE("GPL"); - -/* Module Parameters */ -static int index = SNDRV_DEFAULT_IDX1; -static char *id = SNDRV_DEFAULT_STR1; -module_param(index, int, 0444); -MODULE_PARM_DESC(index, "Index value for SuperH DAC audio."); -module_param(id, charp, 0444); -MODULE_PARM_DESC(id, "ID string for SuperH DAC audio."); - -/* main struct */ -struct snd_sh_dac { - struct snd_card *card; - struct snd_pcm_substream *substream; - struct hrtimer hrtimer; - ktime_t wakeups_per_second; - - int rate; - int empty; - char *data_buffer, *buffer_begin, *buffer_end; - int processed; /* bytes proccesed, to compare with period_size */ - int buffer_size; - struct dac_audio_pdata *pdata; -}; - - -static void dac_audio_start_timer(struct snd_sh_dac *chip) -{ - hrtimer_start(&chip->hrtimer, chip->wakeups_per_second, - HRTIMER_MODE_REL); -} - -static void dac_audio_stop_timer(struct snd_sh_dac *chip) -{ - hrtimer_cancel(&chip->hrtimer); -} - -static void dac_audio_reset(struct snd_sh_dac *chip) -{ - dac_audio_stop_timer(chip); - chip->buffer_begin = chip->buffer_end = chip->data_buffer; - chip->processed = 0; - chip->empty = 1; -} - -static void dac_audio_set_rate(struct snd_sh_dac *chip) -{ - chip->wakeups_per_second = 1000000000 / chip->rate; -} - - -/* PCM INTERFACE */ - -static const struct snd_pcm_hardware snd_sh_dac_pcm_hw = { - .info = (SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_HALF_DUPLEX), - .formats = SNDRV_PCM_FMTBIT_U8, - .rates = SNDRV_PCM_RATE_8000, - .rate_min = 8000, - .rate_max = 8000, - .channels_min = 1, - .channels_max = 1, - .buffer_bytes_max = (48*1024), - .period_bytes_min = 1, - .period_bytes_max = (48*1024), - .periods_min = 1, - .periods_max = 1024, -}; - -static int snd_sh_dac_pcm_open(struct snd_pcm_substream *substream) -{ - struct snd_sh_dac *chip = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - - runtime->hw = snd_sh_dac_pcm_hw; - - chip->substream = substream; - chip->buffer_begin = chip->buffer_end = chip->data_buffer; - chip->processed = 0; - chip->empty = 1; - - chip->pdata->start(chip->pdata); - - return 0; -} - -static int snd_sh_dac_pcm_close(struct snd_pcm_substream *substream) -{ - struct snd_sh_dac *chip = snd_pcm_substream_chip(substream); - - chip->substream = NULL; - - dac_audio_stop_timer(chip); - chip->pdata->stop(chip->pdata); - - return 0; -} - -static int snd_sh_dac_pcm_prepare(struct snd_pcm_substream *substream) -{ - struct snd_sh_dac *chip = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = chip->substream->runtime; - - chip->buffer_size = runtime->buffer_size; - memset(chip->data_buffer, 0, chip->pdata->buffer_size); - - return 0; -} - -static int snd_sh_dac_pcm_trigger(struct snd_pcm_substream *substream, int cmd) -{ - struct snd_sh_dac *chip = snd_pcm_substream_chip(substream); - - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - dac_audio_start_timer(chip); - break; - case SNDRV_PCM_TRIGGER_STOP: - chip->buffer_begin = chip->buffer_end = chip->data_buffer; - chip->processed = 0; - chip->empty = 1; - dac_audio_stop_timer(chip); - break; - default: - return -EINVAL; - } - - return 0; -} - -static int snd_sh_dac_pcm_copy(struct snd_pcm_substream *substream, - int channel, unsigned long pos, - void __user *src, unsigned long count) -{ - /* channel is not used (interleaved data) */ - struct snd_sh_dac *chip = snd_pcm_substream_chip(substream); - - if (copy_from_user_toio(chip->data_buffer + pos, src, count)) - return -EFAULT; - chip->buffer_end = chip->data_buffer + pos + count; - - if (chip->empty) { - chip->empty = 0; - dac_audio_start_timer(chip); - } - - return 0; -} - -static int snd_sh_dac_pcm_copy_kernel(struct snd_pcm_substream *substream, - int channel, unsigned long pos, - void *src, unsigned long count) -{ - /* channel is not used (interleaved data) */ - struct snd_sh_dac *chip = snd_pcm_substream_chip(substream); - - memcpy_toio(chip->data_buffer + pos, src, count); - chip->buffer_end = chip->data_buffer + pos + count; - - if (chip->empty) { - chip->empty = 0; - dac_audio_start_timer(chip); - } - - return 0; -} - -static int snd_sh_dac_pcm_silence(struct snd_pcm_substream *substream, - int channel, unsigned long pos, - unsigned long count) -{ - /* channel is not used (interleaved data) */ - struct snd_sh_dac *chip = snd_pcm_substream_chip(substream); - - memset_io(chip->data_buffer + pos, 0, count); - chip->buffer_end = chip->data_buffer + pos + count; - - if (chip->empty) { - chip->empty = 0; - dac_audio_start_timer(chip); - } - - return 0; -} - -static -snd_pcm_uframes_t snd_sh_dac_pcm_pointer(struct snd_pcm_substream *substream) -{ - struct snd_sh_dac *chip = snd_pcm_substream_chip(substream); - int pointer = chip->buffer_begin - chip->data_buffer; - - return pointer; -} - -/* pcm ops */ -static const struct snd_pcm_ops snd_sh_dac_pcm_ops = { - .open = snd_sh_dac_pcm_open, - .close = snd_sh_dac_pcm_close, - .prepare = snd_sh_dac_pcm_prepare, - .trigger = snd_sh_dac_pcm_trigger, - .pointer = snd_sh_dac_pcm_pointer, - .copy_user = snd_sh_dac_pcm_copy, - .copy_kernel = snd_sh_dac_pcm_copy_kernel, - .fill_silence = snd_sh_dac_pcm_silence, - .mmap = snd_pcm_lib_mmap_iomem, -}; - -static int snd_sh_dac_pcm(struct snd_sh_dac *chip, int device) -{ - int err; - struct snd_pcm *pcm; - - /* device should be always 0 for us */ - err = snd_pcm_new(chip->card, "SH_DAC PCM", device, 1, 0, &pcm); - if (err < 0) - return err; - - pcm->private_data = chip; - strcpy(pcm->name, "SH_DAC PCM"); - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_sh_dac_pcm_ops); - - /* buffer size=48K */ - snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_CONTINUOUS, - NULL, 48 * 1024, 48 * 1024); - - return 0; -} -/* END OF PCM INTERFACE */ - - -/* driver .remove -- destructor */ -static int snd_sh_dac_remove(struct platform_device *devptr) -{ - snd_card_free(platform_get_drvdata(devptr)); - return 0; -} - -/* free -- it has been defined by create */ -static int snd_sh_dac_free(struct snd_sh_dac *chip) -{ - /* release the data */ - kfree(chip->data_buffer); - kfree(chip); - - return 0; -} - -static int snd_sh_dac_dev_free(struct snd_device *device) -{ - struct snd_sh_dac *chip = device->device_data; - - return snd_sh_dac_free(chip); -} - -static enum hrtimer_restart sh_dac_audio_timer(struct hrtimer *handle) -{ - struct snd_sh_dac *chip = container_of(handle, struct snd_sh_dac, - hrtimer); - struct snd_pcm_runtime *runtime = chip->substream->runtime; - ssize_t b_ps = frames_to_bytes(runtime, runtime->period_size); - - if (!chip->empty) { - sh_dac_output(*chip->buffer_begin, chip->pdata->channel); - chip->buffer_begin++; - - chip->processed++; - if (chip->processed >= b_ps) { - chip->processed -= b_ps; - snd_pcm_period_elapsed(chip->substream); - } - - if (chip->buffer_begin == (chip->data_buffer + - chip->buffer_size - 1)) - chip->buffer_begin = chip->data_buffer; - - if (chip->buffer_begin == chip->buffer_end) - chip->empty = 1; - - } - - if (!chip->empty) - hrtimer_start(&chip->hrtimer, chip->wakeups_per_second, - HRTIMER_MODE_REL); - - return HRTIMER_NORESTART; -} - -/* create -- chip-specific constructor for the cards components */ -static int snd_sh_dac_create(struct snd_card *card, - struct platform_device *devptr, - struct snd_sh_dac **rchip) -{ - struct snd_sh_dac *chip; - int err; - - static const struct snd_device_ops ops = { - .dev_free = snd_sh_dac_dev_free, - }; - - *rchip = NULL; - - chip = kzalloc(sizeof(*chip), GFP_KERNEL); - if (chip == NULL) - return -ENOMEM; - - chip->card = card; - - hrtimer_init(&chip->hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); - chip->hrtimer.function = sh_dac_audio_timer; - - dac_audio_reset(chip); - chip->rate = 8000; - dac_audio_set_rate(chip); - - chip->pdata = devptr->dev.platform_data; - - chip->data_buffer = kmalloc(chip->pdata->buffer_size, GFP_KERNEL); - if (chip->data_buffer == NULL) { - kfree(chip); - return -ENOMEM; - } - - err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops); - if (err < 0) { - snd_sh_dac_free(chip); - return err; - } - - *rchip = chip; - - return 0; -} - -/* driver .probe -- constructor */ -static int snd_sh_dac_probe(struct platform_device *devptr) -{ - struct snd_sh_dac *chip; - struct snd_card *card; - int err; - - err = snd_card_new(&devptr->dev, index, id, THIS_MODULE, 0, &card); - if (err < 0) { - snd_printk(KERN_ERR "cannot allocate the card\n"); - return err; - } - - err = snd_sh_dac_create(card, devptr, &chip); - if (err < 0) - goto probe_error; - - err = snd_sh_dac_pcm(chip, 0); - if (err < 0) - goto probe_error; - - strcpy(card->driver, "snd_sh_dac"); - strcpy(card->shortname, "SuperH DAC audio driver"); - printk(KERN_INFO "%s %s", card->longname, card->shortname); - - err = snd_card_register(card); - if (err < 0) - goto probe_error; - - snd_printk(KERN_INFO "ALSA driver for SuperH DAC audio"); - - platform_set_drvdata(devptr, card); - return 0; - -probe_error: - snd_card_free(card); - return err; -} - -/* - * "driver" definition - */ -static struct platform_driver sh_dac_driver = { - .probe = snd_sh_dac_probe, - .remove = snd_sh_dac_remove, - .driver = { - .name = "dac_audio", - }, -}; - -module_platform_driver(sh_dac_driver); From patchwork Fri Jan 13 06:23:24 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christoph Hellwig X-Patchwork-Id: 642859 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 83AD8C678D8 for ; Fri, 13 Jan 2023 06:28:08 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S240997AbjAMG2H (ORCPT ); Fri, 13 Jan 2023 01:28:07 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:33490 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234671AbjAMGYw (ORCPT ); Fri, 13 Jan 2023 01:24:52 -0500 Received: from bombadil.infradead.org (bombadil.infradead.org [IPv6:2607:7c80:54:3::133]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 41A176AD8E; Thu, 12 Jan 2023 22:24:18 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=infradead.org; s=bombadil.20210309; h=Content-Transfer-Encoding: MIME-Version:References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From:Sender :Reply-To:Content-Type:Content-ID:Content-Description; bh=iaAi+zESrNMNvvfEXFwVvV/C96H0o/Wg4Lh/ijTH/Rs=; b=bFRj3MYFOTjA0PSj1DEyvNksix /txq5zuehZaq1Obp5gHKz5id8DzeGGV7lKL1AlhZOUgWtvxuhMVAbMwGri/ic3+f0enD9lYjxMQxR Gf9Y2f2aOQpWUPFvfhpJhFzN7A8d5hLtjyalZeqPDUM7QjO4XAjWCeiOpKaBwU207o9TIBRxH7mXv 9vW0R9Uv9WQi52i2Oie2Pb8ur8xtcT8EDzxlRsm/eP88LuKtf9xnY5QQhes6Rk2Hh9F25LQMh2HOL FXdK9tEz8XfVNXQMf+wriv4ySdq3dT2hm7Zg5AxsfkPpD1KGm+e/o6nTrxQgdrQp+txMqv4euPuCk mWxG2tow==; Received: from [2001:4bb8:181:656b:9509:7d20:8d39:f895] (helo=localhost) by bombadil.infradead.org with esmtpsa (Exim 4.94.2 #2 (Red Hat Linux)) id 1pGDU1-000lXq-5b; Fri, 13 Jan 2023 06:24:09 +0000 From: Christoph Hellwig To: Yoshinori Sato , Rich Felker , Arnd Bergmann , Greg Kroah-Hartman Cc: Laurent Pinchart , Kieran Bingham , Geert Uytterhoeven , linux-kernel@vger.kernel.org, linux-watchdog@vger.kernel.org, devicetree@vger.kernel.org, linux-arch@vger.kernel.org, dmaengine@vger.kernel.org, dri-devel@lists.freedesktop.org, linux-renesas-soc@vger.kernel.org, linux-i2c@vger.kernel.org, linux-input@vger.kernel.org, linux-media@vger.kernel.org, linux-mmc@vger.kernel.org, linux-mtd@lists.infradead.org, netdev@vger.kernel.org, linux-gpio@vger.kernel.org, linux-rtc@vger.kernel.org, linux-spi@vger.kernel.org, linux-serial@vger.kernel.org, linux-usb@vger.kernel.org, linux-fbdev@vger.kernel.org, alsa-devel@alsa-project.org, linux-sh@vger.kernel.org Subject: [PATCH 07/22] cpufreq: remove the sh-cpufreq driver Date: Fri, 13 Jan 2023 07:23:24 +0100 Message-Id: <20230113062339.1909087-8-hch@lst.de> X-Mailer: git-send-email 2.39.0 In-Reply-To: <20230113062339.1909087-1-hch@lst.de> References: <20230113062339.1909087-1-hch@lst.de> MIME-Version: 1.0 X-SRS-Rewrite: SMTP reverse-path rewritten from by bombadil.infradead.org. See http://www.infradead.org/rpr.html Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org Now that arch/sh is removed this driver is dead code. Signed-off-by: Christoph Hellwig --- drivers/cpufreq/Kconfig | 14 --- drivers/cpufreq/Makefile | 1 - drivers/cpufreq/sh-cpufreq.c | 175 ----------------------------------- 3 files changed, 190 deletions(-) delete mode 100644 drivers/cpufreq/sh-cpufreq.c diff --git a/drivers/cpufreq/Kconfig b/drivers/cpufreq/Kconfig index 2a84fc63371e2e..75a7a486308d8c 100644 --- a/drivers/cpufreq/Kconfig +++ b/drivers/cpufreq/Kconfig @@ -298,20 +298,6 @@ config SPARC_US2E_CPUFREQ If in doubt, say N. endif -if SUPERH -config SH_CPU_FREQ - tristate "SuperH CPU Frequency driver" - help - This adds the cpufreq driver for SuperH. Any CPU that supports - clock rate rounding through the clock framework can use this - driver. While it will make the kernel slightly larger, this is - harmless for CPUs that don't support rate rounding. The driver - will also generate a notice in the boot log before disabling - itself if the CPU in question is not capable of rate rounding. - - If unsure, say N. -endif - config QORIQ_CPUFREQ tristate "CPU frequency scaling driver for Freescale QorIQ SoCs" depends on OF && COMMON_CLK diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile index 32a7029e25ed81..9c16e77e3e87c0 100644 --- a/drivers/cpufreq/Makefile +++ b/drivers/cpufreq/Makefile @@ -112,6 +112,5 @@ obj-$(CONFIG_BMIPS_CPUFREQ) += bmips-cpufreq.o obj-$(CONFIG_IA64_ACPI_CPUFREQ) += ia64-acpi-cpufreq.o obj-$(CONFIG_LOONGSON2_CPUFREQ) += loongson2_cpufreq.o obj-$(CONFIG_LOONGSON1_CPUFREQ) += loongson1-cpufreq.o -obj-$(CONFIG_SH_CPU_FREQ) += sh-cpufreq.o obj-$(CONFIG_SPARC_US2E_CPUFREQ) += sparc-us2e-cpufreq.o obj-$(CONFIG_SPARC_US3_CPUFREQ) += sparc-us3-cpufreq.o diff --git a/drivers/cpufreq/sh-cpufreq.c b/drivers/cpufreq/sh-cpufreq.c deleted file mode 100644 index b8704232c27b24..00000000000000 --- a/drivers/cpufreq/sh-cpufreq.c +++ /dev/null @@ -1,175 +0,0 @@ -/* - * cpufreq driver for the SuperH processors. - * - * Copyright (C) 2002 - 2012 Paul Mundt - * Copyright (C) 2002 M. R. Brown - * - * Clock framework bits from arch/avr32/mach-at32ap/cpufreq.c - * - * Copyright (C) 2004-2007 Atmel Corporation - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - */ -#define pr_fmt(fmt) "cpufreq: " fmt - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -static DEFINE_PER_CPU(struct clk, sh_cpuclk); - -struct cpufreq_target { - struct cpufreq_policy *policy; - unsigned int freq; -}; - -static unsigned int sh_cpufreq_get(unsigned int cpu) -{ - return (clk_get_rate(&per_cpu(sh_cpuclk, cpu)) + 500) / 1000; -} - -static long __sh_cpufreq_target(void *arg) -{ - struct cpufreq_target *target = arg; - struct cpufreq_policy *policy = target->policy; - int cpu = policy->cpu; - struct clk *cpuclk = &per_cpu(sh_cpuclk, cpu); - struct cpufreq_freqs freqs; - struct device *dev; - long freq; - - if (smp_processor_id() != cpu) - return -ENODEV; - - dev = get_cpu_device(cpu); - - /* Convert target_freq from kHz to Hz */ - freq = clk_round_rate(cpuclk, target->freq * 1000); - - if (freq < (policy->min * 1000) || freq > (policy->max * 1000)) - return -EINVAL; - - dev_dbg(dev, "requested frequency %u Hz\n", target->freq * 1000); - - freqs.old = sh_cpufreq_get(cpu); - freqs.new = (freq + 500) / 1000; - freqs.flags = 0; - - cpufreq_freq_transition_begin(target->policy, &freqs); - clk_set_rate(cpuclk, freq); - cpufreq_freq_transition_end(target->policy, &freqs, 0); - - dev_dbg(dev, "set frequency %lu Hz\n", freq); - return 0; -} - -/* - * Here we notify other drivers of the proposed change and the final change. - */ -static int sh_cpufreq_target(struct cpufreq_policy *policy, - unsigned int target_freq, - unsigned int relation) -{ - struct cpufreq_target data = { .policy = policy, .freq = target_freq }; - - return work_on_cpu(policy->cpu, __sh_cpufreq_target, &data); -} - -static int sh_cpufreq_verify(struct cpufreq_policy_data *policy) -{ - struct clk *cpuclk = &per_cpu(sh_cpuclk, policy->cpu); - struct cpufreq_frequency_table *freq_table; - - freq_table = cpuclk->nr_freqs ? cpuclk->freq_table : NULL; - if (freq_table) - return cpufreq_frequency_table_verify(policy, freq_table); - - cpufreq_verify_within_cpu_limits(policy); - - policy->min = (clk_round_rate(cpuclk, 1) + 500) / 1000; - policy->max = (clk_round_rate(cpuclk, ~0UL) + 500) / 1000; - - cpufreq_verify_within_cpu_limits(policy); - return 0; -} - -static int sh_cpufreq_cpu_init(struct cpufreq_policy *policy) -{ - unsigned int cpu = policy->cpu; - struct clk *cpuclk = &per_cpu(sh_cpuclk, cpu); - struct cpufreq_frequency_table *freq_table; - struct device *dev; - - dev = get_cpu_device(cpu); - - cpuclk = clk_get(dev, "cpu_clk"); - if (IS_ERR(cpuclk)) { - dev_err(dev, "couldn't get CPU clk\n"); - return PTR_ERR(cpuclk); - } - - freq_table = cpuclk->nr_freqs ? cpuclk->freq_table : NULL; - if (freq_table) { - policy->freq_table = freq_table; - } else { - dev_notice(dev, "no frequency table found, falling back " - "to rate rounding.\n"); - - policy->min = policy->cpuinfo.min_freq = - (clk_round_rate(cpuclk, 1) + 500) / 1000; - policy->max = policy->cpuinfo.max_freq = - (clk_round_rate(cpuclk, ~0UL) + 500) / 1000; - } - - return 0; -} - -static int sh_cpufreq_cpu_exit(struct cpufreq_policy *policy) -{ - unsigned int cpu = policy->cpu; - struct clk *cpuclk = &per_cpu(sh_cpuclk, cpu); - - clk_put(cpuclk); - - return 0; -} - -static struct cpufreq_driver sh_cpufreq_driver = { - .name = "sh", - .flags = CPUFREQ_NO_AUTO_DYNAMIC_SWITCHING, - .get = sh_cpufreq_get, - .target = sh_cpufreq_target, - .verify = sh_cpufreq_verify, - .init = sh_cpufreq_cpu_init, - .exit = sh_cpufreq_cpu_exit, - .attr = cpufreq_generic_attr, -}; - -static int __init sh_cpufreq_module_init(void) -{ - pr_notice("SuperH CPU frequency driver.\n"); - return cpufreq_register_driver(&sh_cpufreq_driver); -} - -static void __exit sh_cpufreq_module_exit(void) -{ - cpufreq_unregister_driver(&sh_cpufreq_driver); -} - -module_init(sh_cpufreq_module_init); -module_exit(sh_cpufreq_module_exit); - -MODULE_AUTHOR("Paul Mundt "); -MODULE_DESCRIPTION("cpufreq driver for SuperH"); -MODULE_LICENSE("GPL"); From patchwork Fri Jan 13 06:23:26 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christoph Hellwig X-Patchwork-Id: 642860 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 79AE6C54EBD for ; Fri, 13 Jan 2023 06:27:57 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S240950AbjAMG1y (ORCPT ); Fri, 13 Jan 2023 01:27:54 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:33512 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S239960AbjAMGZF (ORCPT ); Fri, 13 Jan 2023 01:25:05 -0500 Received: from bombadil.infradead.org (bombadil.infradead.org [IPv6:2607:7c80:54:3::133]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 58A72D5F; Thu, 12 Jan 2023 22:24:26 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=infradead.org; s=bombadil.20210309; h=Content-Transfer-Encoding: MIME-Version:References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From:Sender :Reply-To:Content-Type:Content-ID:Content-Description; bh=2hPC7zlGA9AoDVV3UDFLI3T20RnHyuVZW1qr++X92oI=; b=U0IxPDIbDusxYyls7GAP+XZ9hs WK31Rw57DTsJeVGBg+mDkhc5spH2HTT6S2bZUnUWnMFMzjuRTQxHiqWupbwLk1M9gy0H80/2TyLAr 4yZAcNURNOrPm5QlFyeBEx9lyjEDdoNyEPtXoGtYw9kpeDRvlQIm1jqEylL4Lcd6JGXKqeXaBK+NJ +uk9CHMdgG+2G6uVa800FbCPfygKQQtSqfcvxslcKVFQl/oOPnfpUDUTut6HA5FBLlzfI2NTovRY8 7+tTh7eQy6PkL+5LvQ1o6k2FC089tht54mg8KW+qjbhQzzqpgcZGx2HuDPkTk929Z5PbzaycfkZ5t Zk42lm1g==; Received: from [2001:4bb8:181:656b:9509:7d20:8d39:f895] (helo=localhost) by bombadil.infradead.org with esmtpsa (Exim 4.94.2 #2 (Red Hat Linux)) id 1pGDU8-000lc0-50; Fri, 13 Jan 2023 06:24:16 +0000 From: Christoph Hellwig To: Yoshinori Sato , Rich Felker , Arnd Bergmann , Greg Kroah-Hartman Cc: Laurent Pinchart , Kieran Bingham , Geert Uytterhoeven , linux-kernel@vger.kernel.org, linux-watchdog@vger.kernel.org, devicetree@vger.kernel.org, linux-arch@vger.kernel.org, dmaengine@vger.kernel.org, dri-devel@lists.freedesktop.org, linux-renesas-soc@vger.kernel.org, linux-i2c@vger.kernel.org, linux-input@vger.kernel.org, linux-media@vger.kernel.org, linux-mmc@vger.kernel.org, linux-mtd@lists.infradead.org, netdev@vger.kernel.org, linux-gpio@vger.kernel.org, linux-rtc@vger.kernel.org, linux-spi@vger.kernel.org, linux-serial@vger.kernel.org, linux-usb@vger.kernel.org, linux-fbdev@vger.kernel.org, alsa-devel@alsa-project.org, linux-sh@vger.kernel.org Subject: [PATCH 09/22] i2c: remove i2c-sh7760 Date: Fri, 13 Jan 2023 07:23:26 +0100 Message-Id: <20230113062339.1909087-10-hch@lst.de> X-Mailer: git-send-email 2.39.0 In-Reply-To: <20230113062339.1909087-1-hch@lst.de> References: <20230113062339.1909087-1-hch@lst.de> MIME-Version: 1.0 X-SRS-Rewrite: SMTP reverse-path rewritten from by bombadil.infradead.org. See http://www.infradead.org/rpr.html Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org Now that arch/sh is removed this driver is dead code. Signed-off-by: Christoph Hellwig --- drivers/i2c/busses/Kconfig | 9 - drivers/i2c/busses/Makefile | 1 - drivers/i2c/busses/i2c-sh7760.c | 565 -------------------------------- 3 files changed, 575 deletions(-) delete mode 100644 drivers/i2c/busses/i2c-sh7760.c diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig index 22602c512a6e50..44267a023fd19a 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig @@ -1016,15 +1016,6 @@ config I2C_S3C2410 Say Y here to include support for I2C controller in the Samsung SoCs (S3C, S5Pv210, Exynos). -config I2C_SH7760 - tristate "Renesas SH7760 I2C Controller" - depends on CPU_SUBTYPE_SH7760 - help - This driver supports the 2 I2C interfaces on the Renesas SH7760. - - This driver can also be built as a module. If so, the module - will be called i2c-sh7760. - config I2C_SH_MOBILE tristate "SuperH Mobile I2C Controller" depends on ARCH_RENESAS || COMPILE_TEST diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile index e73cdb1d2b5a85..6be213e5e4dd16 100644 --- a/drivers/i2c/busses/Makefile +++ b/drivers/i2c/busses/Makefile @@ -104,7 +104,6 @@ obj-$(CONFIG_I2C_RIIC) += i2c-riic.o obj-$(CONFIG_I2C_RK3X) += i2c-rk3x.o obj-$(CONFIG_I2C_RZV2M) += i2c-rzv2m.o obj-$(CONFIG_I2C_S3C2410) += i2c-s3c2410.o -obj-$(CONFIG_I2C_SH7760) += i2c-sh7760.o obj-$(CONFIG_I2C_SH_MOBILE) += i2c-sh_mobile.o obj-$(CONFIG_I2C_SIMTEC) += i2c-simtec.o obj-$(CONFIG_I2C_SPRD) += i2c-sprd.o diff --git a/drivers/i2c/busses/i2c-sh7760.c b/drivers/i2c/busses/i2c-sh7760.c deleted file mode 100644 index 319d1fa617c883..00000000000000 --- a/drivers/i2c/busses/i2c-sh7760.c +++ /dev/null @@ -1,565 +0,0 @@ -/* - * I2C bus driver for the SH7760 I2C Interfaces. - * - * (c) 2005-2008 MSC Vertriebsges.m.b.H, Manuel Lauss - * - * licensed under the terms outlined in the file COPYING. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -/* register offsets */ -#define I2CSCR 0x0 /* slave ctrl */ -#define I2CMCR 0x4 /* master ctrl */ -#define I2CSSR 0x8 /* slave status */ -#define I2CMSR 0xC /* master status */ -#define I2CSIER 0x10 /* slave irq enable */ -#define I2CMIER 0x14 /* master irq enable */ -#define I2CCCR 0x18 /* clock dividers */ -#define I2CSAR 0x1c /* slave address */ -#define I2CMAR 0x20 /* master address */ -#define I2CRXTX 0x24 /* data port */ -#define I2CFCR 0x28 /* fifo control */ -#define I2CFSR 0x2C /* fifo status */ -#define I2CFIER 0x30 /* fifo irq enable */ -#define I2CRFDR 0x34 /* rx fifo count */ -#define I2CTFDR 0x38 /* tx fifo count */ - -#define REGSIZE 0x3C - -#define MCR_MDBS 0x80 /* non-fifo mode switch */ -#define MCR_FSCL 0x40 /* override SCL pin */ -#define MCR_FSDA 0x20 /* override SDA pin */ -#define MCR_OBPC 0x10 /* override pins */ -#define MCR_MIE 0x08 /* master if enable */ -#define MCR_TSBE 0x04 -#define MCR_FSB 0x02 /* force stop bit */ -#define MCR_ESG 0x01 /* en startbit gen. */ - -#define MSR_MNR 0x40 /* nack received */ -#define MSR_MAL 0x20 /* arbitration lost */ -#define MSR_MST 0x10 /* sent a stop */ -#define MSR_MDE 0x08 -#define MSR_MDT 0x04 -#define MSR_MDR 0x02 -#define MSR_MAT 0x01 /* slave addr xfer done */ - -#define MIE_MNRE 0x40 /* nack irq en */ -#define MIE_MALE 0x20 /* arblos irq en */ -#define MIE_MSTE 0x10 /* stop irq en */ -#define MIE_MDEE 0x08 -#define MIE_MDTE 0x04 -#define MIE_MDRE 0x02 -#define MIE_MATE 0x01 /* address sent irq en */ - -#define FCR_RFRST 0x02 /* reset rx fifo */ -#define FCR_TFRST 0x01 /* reset tx fifo */ - -#define FSR_TEND 0x04 /* last byte sent */ -#define FSR_RDF 0x02 /* rx fifo trigger */ -#define FSR_TDFE 0x01 /* tx fifo empty */ - -#define FIER_TEIE 0x04 /* tx fifo empty irq en */ -#define FIER_RXIE 0x02 /* rx fifo trig irq en */ -#define FIER_TXIE 0x01 /* tx fifo trig irq en */ - -#define FIFO_SIZE 16 - -struct cami2c { - void __iomem *iobase; - struct i2c_adapter adap; - - /* message processing */ - struct i2c_msg *msg; -#define IDF_SEND 1 -#define IDF_RECV 2 -#define IDF_STOP 4 - int flags; - -#define IDS_DONE 1 -#define IDS_ARBLOST 2 -#define IDS_NACK 4 - int status; - struct completion xfer_done; - - int irq; - struct resource *ioarea; -}; - -static inline void OUT32(struct cami2c *cam, int reg, unsigned long val) -{ - __raw_writel(val, (unsigned long)cam->iobase + reg); -} - -static inline unsigned long IN32(struct cami2c *cam, int reg) -{ - return __raw_readl((unsigned long)cam->iobase + reg); -} - -static irqreturn_t sh7760_i2c_irq(int irq, void *ptr) -{ - struct cami2c *id = ptr; - struct i2c_msg *msg = id->msg; - char *data = msg->buf; - unsigned long msr, fsr, fier, len; - - msr = IN32(id, I2CMSR); - fsr = IN32(id, I2CFSR); - - /* arbitration lost */ - if (msr & MSR_MAL) { - OUT32(id, I2CMCR, 0); - OUT32(id, I2CSCR, 0); - OUT32(id, I2CSAR, 0); - id->status |= IDS_DONE | IDS_ARBLOST; - goto out; - } - - if (msr & MSR_MNR) { - /* NACK handling is very screwed up. After receiving a - * NAK IRQ one has to wait a bit before writing to any - * registers, or the ctl will lock up. After that delay - * do a normal i2c stop. Then wait at least 1 ms before - * attempting another transfer or ctl will stop working - */ - udelay(100); /* wait or risk ctl hang */ - OUT32(id, I2CFCR, FCR_RFRST | FCR_TFRST); - OUT32(id, I2CMCR, MCR_MIE | MCR_FSB); - OUT32(id, I2CFIER, 0); - OUT32(id, I2CMIER, MIE_MSTE); - OUT32(id, I2CSCR, 0); - OUT32(id, I2CSAR, 0); - id->status |= IDS_NACK; - msr &= ~MSR_MAT; - fsr = 0; - /* In some cases the MST bit is also set. */ - } - - /* i2c-stop was sent */ - if (msr & MSR_MST) { - id->status |= IDS_DONE; - goto out; - } - - /* i2c slave addr was sent; set to "normal" operation */ - if (msr & MSR_MAT) - OUT32(id, I2CMCR, MCR_MIE); - - fier = IN32(id, I2CFIER); - - if (fsr & FSR_RDF) { - len = IN32(id, I2CRFDR); - if (msg->len <= len) { - if (id->flags & IDF_STOP) { - OUT32(id, I2CMCR, MCR_MIE | MCR_FSB); - OUT32(id, I2CFIER, 0); - /* manual says: wait >= 0.5 SCL times */ - udelay(5); - /* next int should be MST */ - } else { - id->status |= IDS_DONE; - /* keep the RDF bit: ctrl holds SCL low - * until the setup for the next i2c_msg - * clears this bit. - */ - fsr &= ~FSR_RDF; - } - } - while (msg->len && len) { - *data++ = IN32(id, I2CRXTX); - msg->len--; - len--; - } - - if (msg->len) { - len = (msg->len >= FIFO_SIZE) ? FIFO_SIZE - 1 - : msg->len - 1; - - OUT32(id, I2CFCR, FCR_TFRST | ((len & 0xf) << 4)); - } - - } else if (id->flags & IDF_SEND) { - if ((fsr & FSR_TEND) && (msg->len < 1)) { - if (id->flags & IDF_STOP) { - OUT32(id, I2CMCR, MCR_MIE | MCR_FSB); - } else { - id->status |= IDS_DONE; - /* keep the TEND bit: ctl holds SCL low - * until the setup for the next i2c_msg - * clears this bit. - */ - fsr &= ~FSR_TEND; - } - } - if (fsr & FSR_TDFE) { - while (msg->len && (IN32(id, I2CTFDR) < FIFO_SIZE)) { - OUT32(id, I2CRXTX, *data++); - msg->len--; - } - - if (msg->len < 1) { - fier &= ~FIER_TXIE; - OUT32(id, I2CFIER, fier); - } else { - len = (msg->len >= FIFO_SIZE) ? 2 : 0; - OUT32(id, I2CFCR, - FCR_RFRST | ((len & 3) << 2)); - } - } - } -out: - if (id->status & IDS_DONE) { - OUT32(id, I2CMIER, 0); - OUT32(id, I2CFIER, 0); - id->msg = NULL; - complete(&id->xfer_done); - } - /* clear status flags and ctrl resumes work */ - OUT32(id, I2CMSR, ~msr); - OUT32(id, I2CFSR, ~fsr); - OUT32(id, I2CSSR, 0); - - return IRQ_HANDLED; -} - - -/* prepare and start a master receive operation */ -static void sh7760_i2c_mrecv(struct cami2c *id) -{ - int len; - - id->flags |= IDF_RECV; - - /* set the slave addr reg; otherwise rcv wont work! */ - OUT32(id, I2CSAR, 0xfe); - OUT32(id, I2CMAR, (id->msg->addr << 1) | 1); - - /* adjust rx fifo trigger */ - if (id->msg->len >= FIFO_SIZE) - len = FIFO_SIZE - 1; /* trigger at fifo full */ - else - len = id->msg->len - 1; /* trigger before all received */ - - OUT32(id, I2CFCR, FCR_RFRST | FCR_TFRST); - OUT32(id, I2CFCR, FCR_TFRST | ((len & 0xF) << 4)); - - OUT32(id, I2CMSR, 0); - OUT32(id, I2CMCR, MCR_MIE | MCR_ESG); - OUT32(id, I2CMIER, MIE_MNRE | MIE_MALE | MIE_MSTE | MIE_MATE); - OUT32(id, I2CFIER, FIER_RXIE); -} - -/* prepare and start a master send operation */ -static void sh7760_i2c_msend(struct cami2c *id) -{ - int len; - - id->flags |= IDF_SEND; - - /* set the slave addr reg; otherwise xmit wont work! */ - OUT32(id, I2CSAR, 0xfe); - OUT32(id, I2CMAR, (id->msg->addr << 1) | 0); - - /* adjust tx fifo trigger */ - if (id->msg->len >= FIFO_SIZE) - len = 2; /* trig: 2 bytes left in TX fifo */ - else - len = 0; /* trig: 8 bytes left in TX fifo */ - - OUT32(id, I2CFCR, FCR_RFRST | FCR_TFRST); - OUT32(id, I2CFCR, FCR_RFRST | ((len & 3) << 2)); - - while (id->msg->len && IN32(id, I2CTFDR) < FIFO_SIZE) { - OUT32(id, I2CRXTX, *(id->msg->buf)); - (id->msg->len)--; - (id->msg->buf)++; - } - - OUT32(id, I2CMSR, 0); - OUT32(id, I2CMCR, MCR_MIE | MCR_ESG); - OUT32(id, I2CFSR, 0); - OUT32(id, I2CMIER, MIE_MNRE | MIE_MALE | MIE_MSTE | MIE_MATE); - OUT32(id, I2CFIER, FIER_TEIE | (id->msg->len ? FIER_TXIE : 0)); -} - -static inline int sh7760_i2c_busy_check(struct cami2c *id) -{ - return (IN32(id, I2CMCR) & MCR_FSDA); -} - -static int sh7760_i2c_master_xfer(struct i2c_adapter *adap, - struct i2c_msg *msgs, - int num) -{ - struct cami2c *id = adap->algo_data; - int i, retr; - - if (sh7760_i2c_busy_check(id)) { - dev_err(&adap->dev, "sh7760-i2c%d: bus busy!\n", adap->nr); - return -EBUSY; - } - - i = 0; - while (i < num) { - retr = adap->retries; -retry: - id->flags = ((i == (num-1)) ? IDF_STOP : 0); - id->status = 0; - id->msg = msgs; - init_completion(&id->xfer_done); - - if (msgs->flags & I2C_M_RD) - sh7760_i2c_mrecv(id); - else - sh7760_i2c_msend(id); - - wait_for_completion(&id->xfer_done); - - if (id->status == 0) { - num = -EIO; - break; - } - - if (id->status & IDS_NACK) { - /* wait a bit or i2c module stops working */ - mdelay(1); - num = -EREMOTEIO; - break; - } - - if (id->status & IDS_ARBLOST) { - if (retr--) { - mdelay(2); - goto retry; - } - num = -EREMOTEIO; - break; - } - - msgs++; - i++; - } - - id->msg = NULL; - id->flags = 0; - id->status = 0; - - OUT32(id, I2CMCR, 0); - OUT32(id, I2CMSR, 0); - OUT32(id, I2CMIER, 0); - OUT32(id, I2CFIER, 0); - - /* reset slave module registers too: master mode enables slave - * module for receive ops (ack, data). Without this reset, - * eternal bus activity might be reported after NACK / ARBLOST. - */ - OUT32(id, I2CSCR, 0); - OUT32(id, I2CSAR, 0); - OUT32(id, I2CSSR, 0); - - return num; -} - -static u32 sh7760_i2c_func(struct i2c_adapter *adap) -{ - return I2C_FUNC_I2C | (I2C_FUNC_SMBUS_EMUL & ~I2C_FUNC_SMBUS_QUICK); -} - -static const struct i2c_algorithm sh7760_i2c_algo = { - .master_xfer = sh7760_i2c_master_xfer, - .functionality = sh7760_i2c_func, -}; - -/* calculate CCR register setting for a desired scl clock. SCL clock is - * derived from I2C module clock (iclk) which in turn is derived from - * peripheral module clock (mclk, usually around 33MHz): - * iclk = mclk/(CDF + 1). iclk must be < 20MHz. - * scl = iclk/(SCGD*8 + 20). - */ -static int calc_CCR(unsigned long scl_hz) -{ - struct clk *mclk; - unsigned long mck, m1, dff, odff, iclk; - signed char cdf, cdfm; - int scgd, scgdm, scgds; - - mclk = clk_get(NULL, "peripheral_clk"); - if (IS_ERR(mclk)) { - return PTR_ERR(mclk); - } else { - mck = mclk->rate; - clk_put(mclk); - } - - odff = scl_hz; - scgdm = cdfm = m1 = 0; - for (cdf = 3; cdf >= 0; cdf--) { - iclk = mck / (1 + cdf); - if (iclk >= 20000000) - continue; - scgds = ((iclk / scl_hz) - 20) >> 3; - for (scgd = scgds; (scgd < 63) && scgd <= scgds + 1; scgd++) { - m1 = iclk / (20 + (scgd << 3)); - dff = abs(scl_hz - m1); - if (dff < odff) { - odff = dff; - cdfm = cdf; - scgdm = scgd; - } - } - } - /* fail if more than 25% off of requested SCL */ - if (odff > (scl_hz >> 2)) - return -EINVAL; - - /* create a CCR register value */ - return ((scgdm << 2) | cdfm); -} - -static int sh7760_i2c_probe(struct platform_device *pdev) -{ - struct sh7760_i2c_platdata *pd; - struct resource *res; - struct cami2c *id; - int ret; - - pd = dev_get_platdata(&pdev->dev); - if (!pd) { - dev_err(&pdev->dev, "no platform_data!\n"); - ret = -ENODEV; - goto out0; - } - - id = kzalloc(sizeof(struct cami2c), GFP_KERNEL); - if (!id) { - dev_err(&pdev->dev, "no mem for private data\n"); - ret = -ENOMEM; - goto out0; - } - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) { - dev_err(&pdev->dev, "no mmio resources\n"); - ret = -ENODEV; - goto out1; - } - - id->ioarea = request_mem_region(res->start, REGSIZE, pdev->name); - if (!id->ioarea) { - dev_err(&pdev->dev, "mmio already reserved\n"); - ret = -EBUSY; - goto out1; - } - - id->iobase = ioremap(res->start, REGSIZE); - if (!id->iobase) { - dev_err(&pdev->dev, "cannot ioremap\n"); - ret = -ENODEV; - goto out2; - } - - ret = platform_get_irq(pdev, 0); - if (ret < 0) - goto out3; - id->irq = ret; - - id->adap.nr = pdev->id; - id->adap.algo = &sh7760_i2c_algo; - id->adap.class = I2C_CLASS_HWMON | I2C_CLASS_SPD; - id->adap.retries = 3; - id->adap.algo_data = id; - id->adap.dev.parent = &pdev->dev; - snprintf(id->adap.name, sizeof(id->adap.name), - "SH7760 I2C at %08lx", (unsigned long)res->start); - - OUT32(id, I2CMCR, 0); - OUT32(id, I2CMSR, 0); - OUT32(id, I2CMIER, 0); - OUT32(id, I2CMAR, 0); - OUT32(id, I2CSIER, 0); - OUT32(id, I2CSAR, 0); - OUT32(id, I2CSCR, 0); - OUT32(id, I2CSSR, 0); - OUT32(id, I2CFIER, 0); - OUT32(id, I2CFCR, FCR_RFRST | FCR_TFRST); - OUT32(id, I2CFSR, 0); - - ret = calc_CCR(pd->speed_khz * 1000); - if (ret < 0) { - dev_err(&pdev->dev, "invalid SCL clock: %dkHz\n", - pd->speed_khz); - goto out3; - } - OUT32(id, I2CCCR, ret); - - if (request_irq(id->irq, sh7760_i2c_irq, 0, - SH7760_I2C_DEVNAME, id)) { - dev_err(&pdev->dev, "cannot get irq %d\n", id->irq); - ret = -EBUSY; - goto out3; - } - - ret = i2c_add_numbered_adapter(&id->adap); - if (ret < 0) - goto out4; - - platform_set_drvdata(pdev, id); - - dev_info(&pdev->dev, "%d kHz mmio %08x irq %d\n", - pd->speed_khz, res->start, id->irq); - - return 0; - -out4: - free_irq(id->irq, id); -out3: - iounmap(id->iobase); -out2: - release_resource(id->ioarea); - kfree(id->ioarea); -out1: - kfree(id); -out0: - return ret; -} - -static int sh7760_i2c_remove(struct platform_device *pdev) -{ - struct cami2c *id = platform_get_drvdata(pdev); - - i2c_del_adapter(&id->adap); - free_irq(id->irq, id); - iounmap(id->iobase); - release_resource(id->ioarea); - kfree(id->ioarea); - kfree(id); - - return 0; -} - -static struct platform_driver sh7760_i2c_drv = { - .driver = { - .name = SH7760_I2C_DEVNAME, - }, - .probe = sh7760_i2c_probe, - .remove = sh7760_i2c_remove, -}; - -module_platform_driver(sh7760_i2c_drv); - -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("SH7760 I2C bus driver"); -MODULE_AUTHOR("Manuel Lauss "); From patchwork Fri Jan 13 06:23:29 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christoph Hellwig X-Patchwork-Id: 642861 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 32FD3C678D8 for ; Fri, 13 Jan 2023 06:27:47 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S240906AbjAMG1l (ORCPT ); Fri, 13 Jan 2023 01:27:41 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:60798 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S240573AbjAMGZP (ORCPT ); Fri, 13 Jan 2023 01:25:15 -0500 Received: from bombadil.infradead.org (bombadil.infradead.org [IPv6:2607:7c80:54:3::133]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 5BE1410073; Thu, 12 Jan 2023 22:24:36 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=infradead.org; s=bombadil.20210309; h=Content-Transfer-Encoding: MIME-Version:References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From:Sender :Reply-To:Content-Type:Content-ID:Content-Description; bh=yNX/9/e3mCL8Z9/A5TRWG0UKPW9ZyWcnD51C6LTuRVI=; b=Ylt8A4HngYHMxsdrT3HnhJDlSV iJ170NFOhoE5/jm4B0r2iZEgG/7ENapsBN7EG3eTyLKpN5X9ZYXjsypPqcTfmEHfo+RwMWyPpP/3+ mjrTudLbbjWOokwEpDHR/SYDPQjEdYu2BrhFltpnBqms3qC6BjqFpSVzUExolaX5+7GIWz7XCFYWp EnNcdwUy6QpwLO2RM/m2LT0BcRLf2dwVUO5JUTWY6khIjWo2kMDSALL69dwv9d7JksbiErk0cYjJy F0GEfksn110Oud3Mh6LP7zQRl0CYW85Mx25oaHsuUudRug/Y9kNkATuSeuGsCBnzF27GOv603zDC4 VB09RLNw==; Received: from [2001:4bb8:181:656b:9509:7d20:8d39:f895] (helo=localhost) by bombadil.infradead.org with esmtpsa (Exim 4.94.2 #2 (Red Hat Linux)) id 1pGDUH-000ljq-PK; Fri, 13 Jan 2023 06:24:26 +0000 From: Christoph Hellwig To: Yoshinori Sato , Rich Felker , Arnd Bergmann , Greg Kroah-Hartman Cc: Laurent Pinchart , Kieran Bingham , Geert Uytterhoeven , linux-kernel@vger.kernel.org, linux-watchdog@vger.kernel.org, devicetree@vger.kernel.org, linux-arch@vger.kernel.org, dmaengine@vger.kernel.org, dri-devel@lists.freedesktop.org, linux-renesas-soc@vger.kernel.org, linux-i2c@vger.kernel.org, linux-input@vger.kernel.org, linux-media@vger.kernel.org, linux-mmc@vger.kernel.org, linux-mtd@lists.infradead.org, netdev@vger.kernel.org, linux-gpio@vger.kernel.org, linux-rtc@vger.kernel.org, linux-spi@vger.kernel.org, linux-serial@vger.kernel.org, linux-usb@vger.kernel.org, linux-fbdev@vger.kernel.org, alsa-devel@alsa-project.org, linux-sh@vger.kernel.org Subject: [PATCH 12/22] net/ethernet/8390: remove stnic Date: Fri, 13 Jan 2023 07:23:29 +0100 Message-Id: <20230113062339.1909087-13-hch@lst.de> X-Mailer: git-send-email 2.39.0 In-Reply-To: <20230113062339.1909087-1-hch@lst.de> References: <20230113062339.1909087-1-hch@lst.de> MIME-Version: 1.0 X-SRS-Rewrite: SMTP reverse-path rewritten from by bombadil.infradead.org. See http://www.infradead.org/rpr.html Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org Now that arch/sh is removed this driver is dead code. Signed-off-by: Christoph Hellwig --- drivers/net/ethernet/8390/Kconfig | 12 -- drivers/net/ethernet/8390/Makefile | 1 - drivers/net/ethernet/8390/stnic.c | 302 ----------------------------- 3 files changed, 315 deletions(-) delete mode 100644 drivers/net/ethernet/8390/stnic.c diff --git a/drivers/net/ethernet/8390/Kconfig b/drivers/net/ethernet/8390/Kconfig index eb90de04c88419..a7976743be9ee3 100644 --- a/drivers/net/ethernet/8390/Kconfig +++ b/drivers/net/ethernet/8390/Kconfig @@ -155,18 +155,6 @@ config PCMCIA_PCNET To compile this driver as a module, choose M here: the module will be called pcnet_cs. If unsure, say N. -config STNIC - tristate "National DP83902AV support" - depends on SUPERH - select CRC32 - help - Support for cards based on the National Semiconductor DP83902AV - ST-NIC Serial Network Interface Controller for Twisted Pair. This - is a 10Mbit/sec Ethernet controller. Product overview and specs at - . - - If unsure, say N. - config ULTRA tristate "SMC Ultra support" depends on ISA diff --git a/drivers/net/ethernet/8390/Makefile b/drivers/net/ethernet/8390/Makefile index 85c83c566ec663..3819a3bb75a1c9 100644 --- a/drivers/net/ethernet/8390/Makefile +++ b/drivers/net/ethernet/8390/Makefile @@ -13,7 +13,6 @@ obj-$(CONFIG_NE2000) += ne.o 8390p.o obj-$(CONFIG_NE2K_PCI) += ne2k-pci.o 8390.o obj-$(CONFIG_PCMCIA_AXNET) += axnet_cs.o 8390.o obj-$(CONFIG_PCMCIA_PCNET) += pcnet_cs.o 8390.o -obj-$(CONFIG_STNIC) += stnic.o 8390.o obj-$(CONFIG_ULTRA) += smc-ultra.o 8390.o obj-$(CONFIG_WD80x3) += wd.o 8390.o obj-$(CONFIG_XSURF100) += xsurf100.o diff --git a/drivers/net/ethernet/8390/stnic.c b/drivers/net/ethernet/8390/stnic.c deleted file mode 100644 index bd89ca8a92dfbc..00000000000000 --- a/drivers/net/ethernet/8390/stnic.c +++ /dev/null @@ -1,302 +0,0 @@ -/* stnic.c : A SH7750 specific part of driver for NS DP83902A ST-NIC. - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * Copyright (C) 1999 kaz Kojima - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#ifdef CONFIG_SH_STANDARD_BIOS -#include -#endif - -#include "8390.h" - -#define DRV_NAME "stnic" - -#define byte unsigned char -#define half unsigned short -#define word unsigned int -#define vbyte volatile unsigned char -#define vhalf volatile unsigned short -#define vword volatile unsigned int - -#define STNIC_RUN 0x01 /* 1 == Run, 0 == reset. */ - -#define START_PG 0 /* First page of TX buffer */ -#define STOP_PG 128 /* Last page +1 of RX ring */ - -/* Alias */ -#define STNIC_CR E8390_CMD -#define PG0_RSAR0 EN0_RSARLO -#define PG0_RSAR1 EN0_RSARHI -#define PG0_RBCR0 EN0_RCNTLO -#define PG0_RBCR1 EN0_RCNTHI - -#define CR_RRD E8390_RREAD -#define CR_RWR E8390_RWRITE -#define CR_PG0 E8390_PAGE0 -#define CR_STA E8390_START -#define CR_RDMA E8390_NODMA - -/* FIXME! YOU MUST SET YOUR OWN ETHER ADDRESS. */ -static byte stnic_eadr[6] = -{0x00, 0xc0, 0x6e, 0x00, 0x00, 0x07}; - -static struct net_device *stnic_dev; - -static void stnic_reset (struct net_device *dev); -static void stnic_get_hdr (struct net_device *dev, struct e8390_pkt_hdr *hdr, - int ring_page); -static void stnic_block_input (struct net_device *dev, int count, - struct sk_buff *skb , int ring_offset); -static void stnic_block_output (struct net_device *dev, int count, - const unsigned char *buf, int start_page); - -static void stnic_init (struct net_device *dev); - -static u32 stnic_msg_enable; - -module_param_named(msg_enable, stnic_msg_enable, uint, 0444); -MODULE_PARM_DESC(msg_enable, "Debug message level (see linux/netdevice.h for bitmap)"); - -/* SH7750 specific read/write io. */ -static inline void -STNIC_DELAY (void) -{ - vword trash; - trash = *(vword *) 0xa0000000; - trash = *(vword *) 0xa0000000; - trash = *(vword *) 0xa0000000; -} - -static inline byte -STNIC_READ (int reg) -{ - byte val; - - val = (*(vhalf *) (PA_83902 + ((reg) << 1)) >> 8) & 0xff; - STNIC_DELAY (); - return val; -} - -static inline void -STNIC_WRITE (int reg, byte val) -{ - *(vhalf *) (PA_83902 + ((reg) << 1)) = ((half) (val) << 8); - STNIC_DELAY (); -} - -static int __init stnic_probe(void) -{ - struct net_device *dev; - struct ei_device *ei_local; - int err; - - /* If we are not running on a SolutionEngine, give up now */ - if (! MACH_SE) - return -ENODEV; - - /* New style probing API */ - dev = alloc_ei_netdev(); - if (!dev) - return -ENOMEM; - -#ifdef CONFIG_SH_STANDARD_BIOS - sh_bios_get_node_addr (stnic_eadr); -#endif - eth_hw_addr_set(dev, stnic_eadr); - - /* Set the base address to point to the NIC, not the "real" base! */ - dev->base_addr = 0x1000; - dev->irq = IRQ_STNIC; - dev->netdev_ops = &ei_netdev_ops; - - /* Snarf the interrupt now. There's no point in waiting since we cannot - share and the board will usually be enabled. */ - err = request_irq (dev->irq, ei_interrupt, 0, DRV_NAME, dev); - if (err) { - netdev_emerg(dev, " unable to get IRQ %d.\n", dev->irq); - free_netdev(dev); - return err; - } - - ei_status.name = dev->name; - ei_status.word16 = 1; -#ifdef __LITTLE_ENDIAN__ - ei_status.bigendian = 0; -#else - ei_status.bigendian = 1; -#endif - ei_status.tx_start_page = START_PG; - ei_status.rx_start_page = START_PG + TX_PAGES; - ei_status.stop_page = STOP_PG; - - ei_status.reset_8390 = &stnic_reset; - ei_status.get_8390_hdr = &stnic_get_hdr; - ei_status.block_input = &stnic_block_input; - ei_status.block_output = &stnic_block_output; - - stnic_init (dev); - ei_local = netdev_priv(dev); - ei_local->msg_enable = stnic_msg_enable; - - err = register_netdev(dev); - if (err) { - free_irq(dev->irq, dev); - free_netdev(dev); - return err; - } - stnic_dev = dev; - - netdev_info(dev, "NS ST-NIC 83902A\n"); - - return 0; -} - -static void -stnic_reset (struct net_device *dev) -{ - struct ei_device *ei_local = netdev_priv(dev); - - *(vhalf *) PA_83902_RST = 0; - udelay (5); - netif_warn(ei_local, hw, dev, "8390 reset done (%ld).\n", jiffies); - *(vhalf *) PA_83902_RST = ~0; - udelay (5); -} - -static void -stnic_get_hdr (struct net_device *dev, struct e8390_pkt_hdr *hdr, - int ring_page) -{ - struct ei_device *ei_local = netdev_priv(dev); - - half buf[2]; - - STNIC_WRITE (PG0_RSAR0, 0); - STNIC_WRITE (PG0_RSAR1, ring_page); - STNIC_WRITE (PG0_RBCR0, 4); - STNIC_WRITE (PG0_RBCR1, 0); - STNIC_WRITE (STNIC_CR, CR_RRD | CR_PG0 | CR_STA); - - buf[0] = *(vhalf *) PA_83902_IF; - STNIC_DELAY (); - buf[1] = *(vhalf *) PA_83902_IF; - STNIC_DELAY (); - hdr->next = buf[0] >> 8; - hdr->status = buf[0] & 0xff; -#ifdef __LITTLE_ENDIAN__ - hdr->count = buf[1]; -#else - hdr->count = ((buf[1] >> 8) & 0xff) | (buf[1] << 8); -#endif - - netif_dbg(ei_local, probe, dev, "ring %x status %02x next %02x count %04x.\n", - ring_page, hdr->status, hdr->next, hdr->count); - - STNIC_WRITE (STNIC_CR, CR_RDMA | CR_PG0 | CR_STA); -} - -/* Block input and output, similar to the Crynwr packet driver. If you are - porting to a new ethercard look at the packet driver source for hints. - The HP LAN doesn't use shared memory -- we put the packet - out through the "remote DMA" dataport. */ - -static void -stnic_block_input (struct net_device *dev, int length, struct sk_buff *skb, - int offset) -{ - char *buf = skb->data; - half val; - - STNIC_WRITE (PG0_RSAR0, offset & 0xff); - STNIC_WRITE (PG0_RSAR1, offset >> 8); - STNIC_WRITE (PG0_RBCR0, length & 0xff); - STNIC_WRITE (PG0_RBCR1, length >> 8); - STNIC_WRITE (STNIC_CR, CR_RRD | CR_PG0 | CR_STA); - - if (length & 1) - length++; - - while (length > 0) - { - val = *(vhalf *) PA_83902_IF; -#ifdef __LITTLE_ENDIAN__ - *buf++ = val & 0xff; - *buf++ = val >> 8; -#else - *buf++ = val >> 8; - *buf++ = val & 0xff; -#endif - STNIC_DELAY (); - length -= sizeof (half); - } - - STNIC_WRITE (STNIC_CR, CR_RDMA | CR_PG0 | CR_STA); -} - -static void -stnic_block_output (struct net_device *dev, int length, - const unsigned char *buf, int output_page) -{ - STNIC_WRITE (PG0_RBCR0, 1); /* Write non-zero value */ - STNIC_WRITE (STNIC_CR, CR_RRD | CR_PG0 | CR_STA); - STNIC_DELAY (); - - STNIC_WRITE (PG0_RBCR0, length & 0xff); - STNIC_WRITE (PG0_RBCR1, length >> 8); - STNIC_WRITE (PG0_RSAR0, 0); - STNIC_WRITE (PG0_RSAR1, output_page); - STNIC_WRITE (STNIC_CR, CR_RWR | CR_PG0 | CR_STA); - - if (length & 1) - length++; - - while (length > 0) - { -#ifdef __LITTLE_ENDIAN__ - *(vhalf *) PA_83902_IF = ((half) buf[1] << 8) | buf[0]; -#else - *(vhalf *) PA_83902_IF = ((half) buf[0] << 8) | buf[1]; -#endif - STNIC_DELAY (); - buf += sizeof (half); - length -= sizeof (half); - } - - STNIC_WRITE (STNIC_CR, CR_RDMA | CR_PG0 | CR_STA); -} - -/* This function resets the STNIC if something screws up. */ -static void -stnic_init (struct net_device *dev) -{ - stnic_reset (dev); - NS8390_init (dev, 0); -} - -static void __exit stnic_cleanup(void) -{ - unregister_netdev(stnic_dev); - free_irq(stnic_dev->irq, stnic_dev); - free_netdev(stnic_dev); -} - -module_init(stnic_probe); -module_exit(stnic_cleanup); -MODULE_LICENSE("GPL"); From patchwork Fri Jan 13 06:23:31 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christoph Hellwig X-Patchwork-Id: 642857 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 09AABC61DB3 for ; Fri, 13 Jan 2023 06:28:17 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S241039AbjAMG2O (ORCPT ); Fri, 13 Jan 2023 01:28:14 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:36814 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S240703AbjAMG0K (ORCPT ); Fri, 13 Jan 2023 01:26:10 -0500 Received: from bombadil.infradead.org (bombadil.infradead.org [IPv6:2607:7c80:54:3::133]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id C7D4E59FBA; Thu, 12 Jan 2023 22:24:47 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=infradead.org; s=bombadil.20210309; h=Content-Transfer-Encoding: MIME-Version:References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From:Sender :Reply-To:Content-Type:Content-ID:Content-Description; bh=UYtxIVSpmMH1XYDAY7FJWv5Cfi/HsfZZkleq/nNm9Uw=; b=FGmCCMVyg/J/LDd53VCAmWvvHd SjKDBgOffbXrp1NTrsMhhHv+fKa003jcLOks15DqfShUdbnxAhNIFRM2NSfl7XNQlFYmA2nIB5pd3 18kopN5bw8wlOYCdnpKB6fCAs/R2kJGbMJgqU6leRj/q7GTrVwrCQlwNcduG7xmi3tJMkH4PGwg8t 5NSqH0Z4uJHNdUoGz9t3t0x8nOR8iL/jB6Iq4fOUMDfkW0fbOoSZotzgCKRxKr7TDB8DCS8psj8ep mpDSvDh9CmgJ7bpf8XvejVWWNoIH413VHBYRgX7Ti7jsugFz8NQa+n4/JrcVIP/PeAFvJm9WU/Rhy 7xT7m2yg==; Received: from [2001:4bb8:181:656b:9509:7d20:8d39:f895] (helo=localhost) by bombadil.infradead.org with esmtpsa (Exim 4.94.2 #2 (Red Hat Linux)) id 1pGDUQ-000lrU-4y; Fri, 13 Jan 2023 06:24:35 +0000 From: Christoph Hellwig To: Yoshinori Sato , Rich Felker , Arnd Bergmann , Greg Kroah-Hartman Cc: Laurent Pinchart , Kieran Bingham , Geert Uytterhoeven , linux-kernel@vger.kernel.org, linux-watchdog@vger.kernel.org, devicetree@vger.kernel.org, linux-arch@vger.kernel.org, dmaengine@vger.kernel.org, dri-devel@lists.freedesktop.org, linux-renesas-soc@vger.kernel.org, linux-i2c@vger.kernel.org, linux-input@vger.kernel.org, linux-media@vger.kernel.org, linux-mmc@vger.kernel.org, linux-mtd@lists.infradead.org, netdev@vger.kernel.org, linux-gpio@vger.kernel.org, linux-rtc@vger.kernel.org, linux-spi@vger.kernel.org, linux-serial@vger.kernel.org, linux-usb@vger.kernel.org, linux-fbdev@vger.kernel.org, alsa-devel@alsa-project.org, linux-sh@vger.kernel.org Subject: [PATCH 14/22] remove drivers/sh Date: Fri, 13 Jan 2023 07:23:31 +0100 Message-Id: <20230113062339.1909087-15-hch@lst.de> X-Mailer: git-send-email 2.39.0 In-Reply-To: <20230113062339.1909087-1-hch@lst.de> References: <20230113062339.1909087-1-hch@lst.de> MIME-Version: 1.0 X-SRS-Rewrite: SMTP reverse-path rewritten from by bombadil.infradead.org. See http://www.infradead.org/rpr.html Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org Now that arch/sh is removed these drivers are dead code. Signed-off-by: Christoph Hellwig --- drivers/Makefile | 1 - drivers/sh/Kconfig | 6 - drivers/sh/Makefile | 12 - drivers/sh/clk/Makefile | 4 - drivers/sh/clk/core.c | 624 ---------------- drivers/sh/clk/cpg.c | 477 ------------ drivers/sh/intc/Kconfig | 44 -- drivers/sh/intc/Makefile | 6 - drivers/sh/intc/access.c | 246 ------- drivers/sh/intc/balancing.c | 97 --- drivers/sh/intc/chip.c | 211 ------ drivers/sh/intc/core.c | 501 ------------- drivers/sh/intc/handle.c | 306 -------- drivers/sh/intc/internals.h | 191 ----- drivers/sh/intc/irqdomain.c | 68 -- drivers/sh/intc/userimask.c | 84 --- drivers/sh/intc/virq-debugfs.c | 54 -- drivers/sh/intc/virq.c | 269 ------- drivers/sh/maple/Makefile | 4 - drivers/sh/maple/maple.c | 895 ----------------------- drivers/sh/pm_runtime.c | 40 - drivers/sh/superhyway/Makefile | 8 - drivers/sh/superhyway/superhyway-sysfs.c | 54 -- drivers/sh/superhyway/superhyway.c | 234 ------ include/linux/sh_clk.h | 213 ------ include/linux/superhyway.h | 107 --- 26 files changed, 4756 deletions(-) delete mode 100644 drivers/sh/Kconfig delete mode 100644 drivers/sh/Makefile delete mode 100644 drivers/sh/clk/Makefile delete mode 100644 drivers/sh/clk/core.c delete mode 100644 drivers/sh/clk/cpg.c delete mode 100644 drivers/sh/intc/Kconfig delete mode 100644 drivers/sh/intc/Makefile delete mode 100644 drivers/sh/intc/access.c delete mode 100644 drivers/sh/intc/balancing.c delete mode 100644 drivers/sh/intc/chip.c delete mode 100644 drivers/sh/intc/core.c delete mode 100644 drivers/sh/intc/handle.c delete mode 100644 drivers/sh/intc/internals.h delete mode 100644 drivers/sh/intc/irqdomain.c delete mode 100644 drivers/sh/intc/userimask.c delete mode 100644 drivers/sh/intc/virq-debugfs.c delete mode 100644 drivers/sh/intc/virq.c delete mode 100644 drivers/sh/maple/Makefile delete mode 100644 drivers/sh/maple/maple.c delete mode 100644 drivers/sh/pm_runtime.c delete mode 100644 drivers/sh/superhyway/Makefile delete mode 100644 drivers/sh/superhyway/superhyway-sysfs.c delete mode 100644 drivers/sh/superhyway/superhyway.c delete mode 100644 include/linux/sh_clk.h delete mode 100644 include/linux/superhyway.h diff --git a/drivers/Makefile b/drivers/Makefile index bdf1c66141c9bd..b97a69a4c40b91 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -134,7 +134,6 @@ obj-$(CONFIG_NEW_LEDS) += leds/ obj-$(CONFIG_INFINIBAND) += infiniband/ obj-y += firmware/ obj-$(CONFIG_CRYPTO) += crypto/ -obj-$(CONFIG_SUPERH) += sh/ obj-y += clocksource/ obj-$(CONFIG_DCA) += dca/ obj-$(CONFIG_HID) += hid/ diff --git a/drivers/sh/Kconfig b/drivers/sh/Kconfig deleted file mode 100644 index 3588fcc9c0d23b..00000000000000 --- a/drivers/sh/Kconfig +++ /dev/null @@ -1,6 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-only -menu "SuperH / SH-Mobile Driver Options" - -source "drivers/sh/intc/Kconfig" - -endmenu diff --git a/drivers/sh/Makefile b/drivers/sh/Makefile deleted file mode 100644 index c53262835e85e2..00000000000000 --- a/drivers/sh/Makefile +++ /dev/null @@ -1,12 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0 -# -# Makefile for the SuperH specific drivers. -# -obj-$(CONFIG_SH_INTC) += intc/ -ifneq ($(CONFIG_COMMON_CLK),y) -obj-$(CONFIG_HAVE_CLK) += clk/ -endif -obj-$(CONFIG_MAPLE) += maple/ -obj-$(CONFIG_SUPERHYWAY) += superhyway/ - -obj-y += pm_runtime.o diff --git a/drivers/sh/clk/Makefile b/drivers/sh/clk/Makefile deleted file mode 100644 index 0158ff3ba9d544..00000000000000 --- a/drivers/sh/clk/Makefile +++ /dev/null @@ -1,4 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-only -obj-y := core.o - -obj-$(CONFIG_SH_CLK_CPG) += cpg.o diff --git a/drivers/sh/clk/core.c b/drivers/sh/clk/core.c deleted file mode 100644 index d996782a710642..00000000000000 --- a/drivers/sh/clk/core.c +++ /dev/null @@ -1,624 +0,0 @@ -/* - * SuperH clock framework - * - * Copyright (C) 2005 - 2010 Paul Mundt - * - * This clock framework is derived from the OMAP version by: - * - * Copyright (C) 2004 - 2008 Nokia Corporation - * Written by Tuukka Tikkanen - * - * Modified for omap shared clock framework by Tony Lindgren - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - */ -#define pr_fmt(fmt) "clock: " fmt - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -static LIST_HEAD(clock_list); -static DEFINE_SPINLOCK(clock_lock); -static DEFINE_MUTEX(clock_list_sem); - -/* clock disable operations are not passed on to hardware during boot */ -static int allow_disable; - -void clk_rate_table_build(struct clk *clk, - struct cpufreq_frequency_table *freq_table, - int nr_freqs, - struct clk_div_mult_table *src_table, - unsigned long *bitmap) -{ - unsigned long mult, div; - unsigned long freq; - int i; - - clk->nr_freqs = nr_freqs; - - for (i = 0; i < nr_freqs; i++) { - div = 1; - mult = 1; - - if (src_table->divisors && i < src_table->nr_divisors) - div = src_table->divisors[i]; - - if (src_table->multipliers && i < src_table->nr_multipliers) - mult = src_table->multipliers[i]; - - if (!div || !mult || (bitmap && !test_bit(i, bitmap))) - freq = CPUFREQ_ENTRY_INVALID; - else - freq = clk->parent->rate * mult / div; - - freq_table[i].driver_data = i; - freq_table[i].frequency = freq; - } - - /* Termination entry */ - freq_table[i].driver_data = i; - freq_table[i].frequency = CPUFREQ_TABLE_END; -} - -struct clk_rate_round_data; - -struct clk_rate_round_data { - unsigned long rate; - unsigned int min, max; - long (*func)(unsigned int, struct clk_rate_round_data *); - void *arg; -}; - -#define for_each_frequency(pos, r, freq) \ - for (pos = r->min, freq = r->func(pos, r); \ - pos <= r->max; pos++, freq = r->func(pos, r)) \ - if (unlikely(freq == 0)) \ - ; \ - else - -static long clk_rate_round_helper(struct clk_rate_round_data *rounder) -{ - unsigned long rate_error, rate_error_prev = ~0UL; - unsigned long highest, lowest, freq; - long rate_best_fit = -ENOENT; - int i; - - highest = 0; - lowest = ~0UL; - - for_each_frequency(i, rounder, freq) { - if (freq > highest) - highest = freq; - if (freq < lowest) - lowest = freq; - - rate_error = abs(freq - rounder->rate); - if (rate_error < rate_error_prev) { - rate_best_fit = freq; - rate_error_prev = rate_error; - } - - if (rate_error == 0) - break; - } - - if (rounder->rate >= highest) - rate_best_fit = highest; - if (rounder->rate <= lowest) - rate_best_fit = lowest; - - return rate_best_fit; -} - -static long clk_rate_table_iter(unsigned int pos, - struct clk_rate_round_data *rounder) -{ - struct cpufreq_frequency_table *freq_table = rounder->arg; - unsigned long freq = freq_table[pos].frequency; - - if (freq == CPUFREQ_ENTRY_INVALID) - freq = 0; - - return freq; -} - -long clk_rate_table_round(struct clk *clk, - struct cpufreq_frequency_table *freq_table, - unsigned long rate) -{ - struct clk_rate_round_data table_round = { - .min = 0, - .max = clk->nr_freqs - 1, - .func = clk_rate_table_iter, - .arg = freq_table, - .rate = rate, - }; - - if (clk->nr_freqs < 1) - return -ENOSYS; - - return clk_rate_round_helper(&table_round); -} - -static long clk_rate_div_range_iter(unsigned int pos, - struct clk_rate_round_data *rounder) -{ - return clk_get_rate(rounder->arg) / pos; -} - -long clk_rate_div_range_round(struct clk *clk, unsigned int div_min, - unsigned int div_max, unsigned long rate) -{ - struct clk_rate_round_data div_range_round = { - .min = div_min, - .max = div_max, - .func = clk_rate_div_range_iter, - .arg = clk_get_parent(clk), - .rate = rate, - }; - - return clk_rate_round_helper(&div_range_round); -} - -static long clk_rate_mult_range_iter(unsigned int pos, - struct clk_rate_round_data *rounder) -{ - return clk_get_rate(rounder->arg) * pos; -} - -long clk_rate_mult_range_round(struct clk *clk, unsigned int mult_min, - unsigned int mult_max, unsigned long rate) -{ - struct clk_rate_round_data mult_range_round = { - .min = mult_min, - .max = mult_max, - .func = clk_rate_mult_range_iter, - .arg = clk_get_parent(clk), - .rate = rate, - }; - - return clk_rate_round_helper(&mult_range_round); -} - -int clk_rate_table_find(struct clk *clk, - struct cpufreq_frequency_table *freq_table, - unsigned long rate) -{ - struct cpufreq_frequency_table *pos; - int idx; - - cpufreq_for_each_valid_entry_idx(pos, freq_table, idx) - if (pos->frequency == rate) - return idx; - - return -ENOENT; -} - -/* Used for clocks that always have same value as the parent clock */ -unsigned long followparent_recalc(struct clk *clk) -{ - return clk->parent ? clk->parent->rate : 0; -} - -int clk_reparent(struct clk *child, struct clk *parent) -{ - list_del_init(&child->sibling); - if (parent) - list_add(&child->sibling, &parent->children); - child->parent = parent; - - return 0; -} - -/* Propagate rate to children */ -void propagate_rate(struct clk *tclk) -{ - struct clk *clkp; - - list_for_each_entry(clkp, &tclk->children, sibling) { - if (clkp->ops && clkp->ops->recalc) - clkp->rate = clkp->ops->recalc(clkp); - - propagate_rate(clkp); - } -} - -static void __clk_disable(struct clk *clk) -{ - if (WARN(!clk->usecount, "Trying to disable clock %p with 0 usecount\n", - clk)) - return; - - if (!(--clk->usecount)) { - if (likely(allow_disable && clk->ops && clk->ops->disable)) - clk->ops->disable(clk); - if (likely(clk->parent)) - __clk_disable(clk->parent); - } -} - -void clk_disable(struct clk *clk) -{ - unsigned long flags; - - if (!clk) - return; - - spin_lock_irqsave(&clock_lock, flags); - __clk_disable(clk); - spin_unlock_irqrestore(&clock_lock, flags); -} -EXPORT_SYMBOL_GPL(clk_disable); - -static int __clk_enable(struct clk *clk) -{ - int ret = 0; - - if (clk->usecount++ == 0) { - if (clk->parent) { - ret = __clk_enable(clk->parent); - if (unlikely(ret)) - goto err; - } - - if (clk->ops && clk->ops->enable) { - ret = clk->ops->enable(clk); - if (ret) { - if (clk->parent) - __clk_disable(clk->parent); - goto err; - } - } - } - - return ret; -err: - clk->usecount--; - return ret; -} - -int clk_enable(struct clk *clk) -{ - unsigned long flags; - int ret; - - if (!clk) - return -EINVAL; - - spin_lock_irqsave(&clock_lock, flags); - ret = __clk_enable(clk); - spin_unlock_irqrestore(&clock_lock, flags); - - return ret; -} -EXPORT_SYMBOL_GPL(clk_enable); - -static LIST_HEAD(root_clks); - -/** - * recalculate_root_clocks - recalculate and propagate all root clocks - * - * Recalculates all root clocks (clocks with no parent), which if the - * clock's .recalc is set correctly, should also propagate their rates. - * Called at init. - */ -void recalculate_root_clocks(void) -{ - struct clk *clkp; - - list_for_each_entry(clkp, &root_clks, sibling) { - if (clkp->ops && clkp->ops->recalc) - clkp->rate = clkp->ops->recalc(clkp); - propagate_rate(clkp); - } -} - -static struct clk_mapping dummy_mapping; - -static struct clk *lookup_root_clock(struct clk *clk) -{ - while (clk->parent) - clk = clk->parent; - - return clk; -} - -static int clk_establish_mapping(struct clk *clk) -{ - struct clk_mapping *mapping = clk->mapping; - - /* - * Propagate mappings. - */ - if (!mapping) { - struct clk *clkp; - - /* - * dummy mapping for root clocks with no specified ranges - */ - if (!clk->parent) { - clk->mapping = &dummy_mapping; - goto out; - } - - /* - * If we're on a child clock and it provides no mapping of its - * own, inherit the mapping from its root clock. - */ - clkp = lookup_root_clock(clk); - mapping = clkp->mapping; - BUG_ON(!mapping); - } - - /* - * Establish initial mapping. - */ - if (!mapping->base && mapping->phys) { - kref_init(&mapping->ref); - - mapping->base = ioremap(mapping->phys, mapping->len); - if (unlikely(!mapping->base)) - return -ENXIO; - } else if (mapping->base) { - /* - * Bump the refcount for an existing mapping - */ - kref_get(&mapping->ref); - } - - clk->mapping = mapping; -out: - clk->mapped_reg = clk->mapping->base; - clk->mapped_reg += (phys_addr_t)clk->enable_reg - clk->mapping->phys; - return 0; -} - -static void clk_destroy_mapping(struct kref *kref) -{ - struct clk_mapping *mapping; - - mapping = container_of(kref, struct clk_mapping, ref); - - iounmap(mapping->base); -} - -static void clk_teardown_mapping(struct clk *clk) -{ - struct clk_mapping *mapping = clk->mapping; - - /* Nothing to do */ - if (mapping == &dummy_mapping) - goto out; - - kref_put(&mapping->ref, clk_destroy_mapping); - clk->mapping = NULL; -out: - clk->mapped_reg = NULL; -} - -int clk_register(struct clk *clk) -{ - int ret; - - if (IS_ERR_OR_NULL(clk)) - return -EINVAL; - - /* - * trap out already registered clocks - */ - if (clk->node.next || clk->node.prev) - return 0; - - mutex_lock(&clock_list_sem); - - INIT_LIST_HEAD(&clk->children); - clk->usecount = 0; - - ret = clk_establish_mapping(clk); - if (unlikely(ret)) - goto out_unlock; - - if (clk->parent) - list_add(&clk->sibling, &clk->parent->children); - else - list_add(&clk->sibling, &root_clks); - - list_add(&clk->node, &clock_list); - -#ifdef CONFIG_SH_CLK_CPG_LEGACY - if (clk->ops && clk->ops->init) - clk->ops->init(clk); -#endif - -out_unlock: - mutex_unlock(&clock_list_sem); - - return ret; -} -EXPORT_SYMBOL_GPL(clk_register); - -void clk_unregister(struct clk *clk) -{ - mutex_lock(&clock_list_sem); - list_del(&clk->sibling); - list_del(&clk->node); - clk_teardown_mapping(clk); - mutex_unlock(&clock_list_sem); -} -EXPORT_SYMBOL_GPL(clk_unregister); - -void clk_enable_init_clocks(void) -{ - struct clk *clkp; - - list_for_each_entry(clkp, &clock_list, node) - if (clkp->flags & CLK_ENABLE_ON_INIT) - clk_enable(clkp); -} - -unsigned long clk_get_rate(struct clk *clk) -{ - if (!clk) - return 0; - - return clk->rate; -} -EXPORT_SYMBOL_GPL(clk_get_rate); - -int clk_set_rate(struct clk *clk, unsigned long rate) -{ - int ret = -EOPNOTSUPP; - unsigned long flags; - - if (!clk) - return 0; - - spin_lock_irqsave(&clock_lock, flags); - - if (likely(clk->ops && clk->ops->set_rate)) { - ret = clk->ops->set_rate(clk, rate); - if (ret != 0) - goto out_unlock; - } else { - clk->rate = rate; - ret = 0; - } - - if (clk->ops && clk->ops->recalc) - clk->rate = clk->ops->recalc(clk); - - propagate_rate(clk); - -out_unlock: - spin_unlock_irqrestore(&clock_lock, flags); - - return ret; -} -EXPORT_SYMBOL_GPL(clk_set_rate); - -int clk_set_parent(struct clk *clk, struct clk *parent) -{ - unsigned long flags; - int ret = -EINVAL; - - if (!parent || !clk) - return ret; - if (clk->parent == parent) - return 0; - - spin_lock_irqsave(&clock_lock, flags); - if (clk->usecount == 0) { - if (clk->ops->set_parent) - ret = clk->ops->set_parent(clk, parent); - else - ret = clk_reparent(clk, parent); - - if (ret == 0) { - if (clk->ops->recalc) - clk->rate = clk->ops->recalc(clk); - pr_debug("set parent of %p to %p (new rate %ld)\n", - clk, clk->parent, clk->rate); - propagate_rate(clk); - } - } else - ret = -EBUSY; - spin_unlock_irqrestore(&clock_lock, flags); - - return ret; -} -EXPORT_SYMBOL_GPL(clk_set_parent); - -struct clk *clk_get_parent(struct clk *clk) -{ - if (!clk) - return NULL; - - return clk->parent; -} -EXPORT_SYMBOL_GPL(clk_get_parent); - -long clk_round_rate(struct clk *clk, unsigned long rate) -{ - if (!clk) - return 0; - - if (likely(clk->ops && clk->ops->round_rate)) { - unsigned long flags, rounded; - - spin_lock_irqsave(&clock_lock, flags); - rounded = clk->ops->round_rate(clk, rate); - spin_unlock_irqrestore(&clock_lock, flags); - - return rounded; - } - - return clk_get_rate(clk); -} -EXPORT_SYMBOL_GPL(clk_round_rate); - -#ifdef CONFIG_PM -static void clks_core_resume(void) -{ - struct clk *clkp; - - list_for_each_entry(clkp, &clock_list, node) { - if (likely(clkp->usecount && clkp->ops)) { - unsigned long rate = clkp->rate; - - if (likely(clkp->ops->set_parent)) - clkp->ops->set_parent(clkp, - clkp->parent); - if (likely(clkp->ops->set_rate)) - clkp->ops->set_rate(clkp, rate); - else if (likely(clkp->ops->recalc)) - clkp->rate = clkp->ops->recalc(clkp); - } - } -} - -static struct syscore_ops clks_syscore_ops = { - .resume = clks_core_resume, -}; - -static int __init clk_syscore_init(void) -{ - register_syscore_ops(&clks_syscore_ops); - - return 0; -} -subsys_initcall(clk_syscore_init); -#endif - -static int __init clk_late_init(void) -{ - unsigned long flags; - struct clk *clk; - - /* disable all clocks with zero use count */ - mutex_lock(&clock_list_sem); - spin_lock_irqsave(&clock_lock, flags); - - list_for_each_entry(clk, &clock_list, node) - if (!clk->usecount && clk->ops && clk->ops->disable) - clk->ops->disable(clk); - - /* from now on allow clock disable operations */ - allow_disable = 1; - - spin_unlock_irqrestore(&clock_lock, flags); - mutex_unlock(&clock_list_sem); - return 0; -} -late_initcall(clk_late_init); diff --git a/drivers/sh/clk/cpg.c b/drivers/sh/clk/cpg.c deleted file mode 100644 index fd72d9088bdcbc..00000000000000 --- a/drivers/sh/clk/cpg.c +++ /dev/null @@ -1,477 +0,0 @@ -/* - * Helper routines for SuperH Clock Pulse Generator blocks (CPG). - * - * Copyright (C) 2010 Magnus Damm - * Copyright (C) 2010 - 2012 Paul Mundt - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - */ -#include -#include -#include -#include -#include - -#define CPG_CKSTP_BIT BIT(8) - -static unsigned int sh_clk_read(struct clk *clk) -{ - if (clk->flags & CLK_ENABLE_REG_8BIT) - return ioread8(clk->mapped_reg); - else if (clk->flags & CLK_ENABLE_REG_16BIT) - return ioread16(clk->mapped_reg); - - return ioread32(clk->mapped_reg); -} - -static void sh_clk_write(int value, struct clk *clk) -{ - if (clk->flags & CLK_ENABLE_REG_8BIT) - iowrite8(value, clk->mapped_reg); - else if (clk->flags & CLK_ENABLE_REG_16BIT) - iowrite16(value, clk->mapped_reg); - else - iowrite32(value, clk->mapped_reg); -} - -static int sh_clk_mstp_enable(struct clk *clk) -{ - sh_clk_write(sh_clk_read(clk) & ~(1 << clk->enable_bit), clk); - if (clk->status_reg) { - unsigned int (*read)(const void __iomem *addr); - int i; - void __iomem *mapped_status = (phys_addr_t)clk->status_reg - - (phys_addr_t)clk->enable_reg + clk->mapped_reg; - - if (clk->flags & CLK_ENABLE_REG_8BIT) - read = ioread8; - else if (clk->flags & CLK_ENABLE_REG_16BIT) - read = ioread16; - else - read = ioread32; - - for (i = 1000; - (read(mapped_status) & (1 << clk->enable_bit)) && i; - i--) - cpu_relax(); - if (!i) { - pr_err("cpg: failed to enable %p[%d]\n", - clk->enable_reg, clk->enable_bit); - return -ETIMEDOUT; - } - } - return 0; -} - -static void sh_clk_mstp_disable(struct clk *clk) -{ - sh_clk_write(sh_clk_read(clk) | (1 << clk->enable_bit), clk); -} - -static struct sh_clk_ops sh_clk_mstp_clk_ops = { - .enable = sh_clk_mstp_enable, - .disable = sh_clk_mstp_disable, - .recalc = followparent_recalc, -}; - -int __init sh_clk_mstp_register(struct clk *clks, int nr) -{ - struct clk *clkp; - int ret = 0; - int k; - - for (k = 0; !ret && (k < nr); k++) { - clkp = clks + k; - clkp->ops = &sh_clk_mstp_clk_ops; - ret |= clk_register(clkp); - } - - return ret; -} - -/* - * Div/mult table lookup helpers - */ -static inline struct clk_div_table *clk_to_div_table(struct clk *clk) -{ - return clk->priv; -} - -static inline struct clk_div_mult_table *clk_to_div_mult_table(struct clk *clk) -{ - return clk_to_div_table(clk)->div_mult_table; -} - -/* - * Common div ops - */ -static long sh_clk_div_round_rate(struct clk *clk, unsigned long rate) -{ - return clk_rate_table_round(clk, clk->freq_table, rate); -} - -static unsigned long sh_clk_div_recalc(struct clk *clk) -{ - struct clk_div_mult_table *table = clk_to_div_mult_table(clk); - unsigned int idx; - - clk_rate_table_build(clk, clk->freq_table, table->nr_divisors, - table, clk->arch_flags ? &clk->arch_flags : NULL); - - idx = (sh_clk_read(clk) >> clk->enable_bit) & clk->div_mask; - - return clk->freq_table[idx].frequency; -} - -static int sh_clk_div_set_rate(struct clk *clk, unsigned long rate) -{ - struct clk_div_table *dt = clk_to_div_table(clk); - unsigned long value; - int idx; - - idx = clk_rate_table_find(clk, clk->freq_table, rate); - if (idx < 0) - return idx; - - value = sh_clk_read(clk); - value &= ~(clk->div_mask << clk->enable_bit); - value |= (idx << clk->enable_bit); - sh_clk_write(value, clk); - - /* XXX: Should use a post-change notifier */ - if (dt->kick) - dt->kick(clk); - - return 0; -} - -static int sh_clk_div_enable(struct clk *clk) -{ - if (clk->div_mask == SH_CLK_DIV6_MSK) { - int ret = sh_clk_div_set_rate(clk, clk->rate); - if (ret < 0) - return ret; - } - - sh_clk_write(sh_clk_read(clk) & ~CPG_CKSTP_BIT, clk); - return 0; -} - -static void sh_clk_div_disable(struct clk *clk) -{ - unsigned int val; - - val = sh_clk_read(clk); - val |= CPG_CKSTP_BIT; - - /* - * div6 clocks require the divisor field to be non-zero or the - * above CKSTP toggle silently fails. Ensure that the divisor - * array is reset to its initial state on disable. - */ - if (clk->flags & CLK_MASK_DIV_ON_DISABLE) - val |= clk->div_mask; - - sh_clk_write(val, clk); -} - -static struct sh_clk_ops sh_clk_div_clk_ops = { - .recalc = sh_clk_div_recalc, - .set_rate = sh_clk_div_set_rate, - .round_rate = sh_clk_div_round_rate, -}; - -static struct sh_clk_ops sh_clk_div_enable_clk_ops = { - .recalc = sh_clk_div_recalc, - .set_rate = sh_clk_div_set_rate, - .round_rate = sh_clk_div_round_rate, - .enable = sh_clk_div_enable, - .disable = sh_clk_div_disable, -}; - -static int __init sh_clk_init_parent(struct clk *clk) -{ - u32 val; - - if (clk->parent) - return 0; - - if (!clk->parent_table || !clk->parent_num) - return 0; - - if (!clk->src_width) { - pr_err("sh_clk_init_parent: cannot select parent clock\n"); - return -EINVAL; - } - - val = (sh_clk_read(clk) >> clk->src_shift); - val &= (1 << clk->src_width) - 1; - - if (val >= clk->parent_num) { - pr_err("sh_clk_init_parent: parent table size failed\n"); - return -EINVAL; - } - - clk_reparent(clk, clk->parent_table[val]); - if (!clk->parent) { - pr_err("sh_clk_init_parent: unable to set parent"); - return -EINVAL; - } - - return 0; -} - -static int __init sh_clk_div_register_ops(struct clk *clks, int nr, - struct clk_div_table *table, struct sh_clk_ops *ops) -{ - struct clk *clkp; - void *freq_table; - int nr_divs = table->div_mult_table->nr_divisors; - int freq_table_size = sizeof(struct cpufreq_frequency_table); - int ret = 0; - int k; - - freq_table_size *= (nr_divs + 1); - freq_table = kcalloc(nr, freq_table_size, GFP_KERNEL); - if (!freq_table) { - pr_err("%s: unable to alloc memory\n", __func__); - return -ENOMEM; - } - - for (k = 0; !ret && (k < nr); k++) { - clkp = clks + k; - - clkp->ops = ops; - clkp->priv = table; - - clkp->freq_table = freq_table + (k * freq_table_size); - clkp->freq_table[nr_divs].frequency = CPUFREQ_TABLE_END; - - ret = clk_register(clkp); - if (ret == 0) - ret = sh_clk_init_parent(clkp); - } - - return ret; -} - -/* - * div6 support - */ -static int sh_clk_div6_divisors[64] = { - 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, - 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, - 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, - 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64 -}; - -static struct clk_div_mult_table div6_div_mult_table = { - .divisors = sh_clk_div6_divisors, - .nr_divisors = ARRAY_SIZE(sh_clk_div6_divisors), -}; - -static struct clk_div_table sh_clk_div6_table = { - .div_mult_table = &div6_div_mult_table, -}; - -static int sh_clk_div6_set_parent(struct clk *clk, struct clk *parent) -{ - struct clk_div_mult_table *table = clk_to_div_mult_table(clk); - u32 value; - int ret, i; - - if (!clk->parent_table || !clk->parent_num) - return -EINVAL; - - /* Search the parent */ - for (i = 0; i < clk->parent_num; i++) - if (clk->parent_table[i] == parent) - break; - - if (i == clk->parent_num) - return -ENODEV; - - ret = clk_reparent(clk, parent); - if (ret < 0) - return ret; - - value = sh_clk_read(clk) & - ~(((1 << clk->src_width) - 1) << clk->src_shift); - - sh_clk_write(value | (i << clk->src_shift), clk); - - /* Rebuild the frequency table */ - clk_rate_table_build(clk, clk->freq_table, table->nr_divisors, - table, NULL); - - return 0; -} - -static struct sh_clk_ops sh_clk_div6_reparent_clk_ops = { - .recalc = sh_clk_div_recalc, - .round_rate = sh_clk_div_round_rate, - .set_rate = sh_clk_div_set_rate, - .enable = sh_clk_div_enable, - .disable = sh_clk_div_disable, - .set_parent = sh_clk_div6_set_parent, -}; - -int __init sh_clk_div6_register(struct clk *clks, int nr) -{ - return sh_clk_div_register_ops(clks, nr, &sh_clk_div6_table, - &sh_clk_div_enable_clk_ops); -} - -int __init sh_clk_div6_reparent_register(struct clk *clks, int nr) -{ - return sh_clk_div_register_ops(clks, nr, &sh_clk_div6_table, - &sh_clk_div6_reparent_clk_ops); -} - -/* - * div4 support - */ -static int sh_clk_div4_set_parent(struct clk *clk, struct clk *parent) -{ - struct clk_div_mult_table *table = clk_to_div_mult_table(clk); - u32 value; - int ret; - - /* we really need a better way to determine parent index, but for - * now assume internal parent comes with CLK_ENABLE_ON_INIT set, - * no CLK_ENABLE_ON_INIT means external clock... - */ - - if (parent->flags & CLK_ENABLE_ON_INIT) - value = sh_clk_read(clk) & ~(1 << 7); - else - value = sh_clk_read(clk) | (1 << 7); - - ret = clk_reparent(clk, parent); - if (ret < 0) - return ret; - - sh_clk_write(value, clk); - - /* Rebiuld the frequency table */ - clk_rate_table_build(clk, clk->freq_table, table->nr_divisors, - table, &clk->arch_flags); - - return 0; -} - -static struct sh_clk_ops sh_clk_div4_reparent_clk_ops = { - .recalc = sh_clk_div_recalc, - .set_rate = sh_clk_div_set_rate, - .round_rate = sh_clk_div_round_rate, - .enable = sh_clk_div_enable, - .disable = sh_clk_div_disable, - .set_parent = sh_clk_div4_set_parent, -}; - -int __init sh_clk_div4_register(struct clk *clks, int nr, - struct clk_div4_table *table) -{ - return sh_clk_div_register_ops(clks, nr, table, &sh_clk_div_clk_ops); -} - -int __init sh_clk_div4_enable_register(struct clk *clks, int nr, - struct clk_div4_table *table) -{ - return sh_clk_div_register_ops(clks, nr, table, - &sh_clk_div_enable_clk_ops); -} - -int __init sh_clk_div4_reparent_register(struct clk *clks, int nr, - struct clk_div4_table *table) -{ - return sh_clk_div_register_ops(clks, nr, table, - &sh_clk_div4_reparent_clk_ops); -} - -/* FSI-DIV */ -static unsigned long fsidiv_recalc(struct clk *clk) -{ - u32 value; - - value = __raw_readl(clk->mapping->base); - - value >>= 16; - if (value < 2) - return clk->parent->rate; - - return clk->parent->rate / value; -} - -static long fsidiv_round_rate(struct clk *clk, unsigned long rate) -{ - return clk_rate_div_range_round(clk, 1, 0xffff, rate); -} - -static void fsidiv_disable(struct clk *clk) -{ - __raw_writel(0, clk->mapping->base); -} - -static int fsidiv_enable(struct clk *clk) -{ - u32 value; - - value = __raw_readl(clk->mapping->base) >> 16; - if (value < 2) - return 0; - - __raw_writel((value << 16) | 0x3, clk->mapping->base); - - return 0; -} - -static int fsidiv_set_rate(struct clk *clk, unsigned long rate) -{ - int idx; - - idx = (clk->parent->rate / rate) & 0xffff; - if (idx < 2) - __raw_writel(0, clk->mapping->base); - else - __raw_writel(idx << 16, clk->mapping->base); - - return 0; -} - -static struct sh_clk_ops fsidiv_clk_ops = { - .recalc = fsidiv_recalc, - .round_rate = fsidiv_round_rate, - .set_rate = fsidiv_set_rate, - .enable = fsidiv_enable, - .disable = fsidiv_disable, -}; - -int __init sh_clk_fsidiv_register(struct clk *clks, int nr) -{ - struct clk_mapping *map; - int i; - - for (i = 0; i < nr; i++) { - - map = kzalloc(sizeof(struct clk_mapping), GFP_KERNEL); - if (!map) { - pr_err("%s: unable to alloc memory\n", __func__); - return -ENOMEM; - } - - /* clks[i].enable_reg came from SH_CLK_FSIDIV() */ - map->phys = (phys_addr_t)clks[i].enable_reg; - map->len = 8; - - clks[i].enable_reg = 0; /* remove .enable_reg */ - clks[i].ops = &fsidiv_clk_ops; - clks[i].mapping = map; - - clk_register(&clks[i]); - } - - return 0; -} diff --git a/drivers/sh/intc/Kconfig b/drivers/sh/intc/Kconfig deleted file mode 100644 index 5c701709fef528..00000000000000 --- a/drivers/sh/intc/Kconfig +++ /dev/null @@ -1,44 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-only -config SH_INTC - bool - select IRQ_DOMAIN - -if SH_INTC - -comment "Interrupt controller options" - -config INTC_USERIMASK - bool "Userspace interrupt masking support" - depends on (SUPERH && CPU_SH4A) || COMPILE_TEST - help - This enables support for hardware-assisted userspace hardirq - masking. - - SH-4A and newer interrupt blocks all support a special shadowed - page with all non-masking registers obscured when mapped in to - userspace. This is primarily for use by userspace device - drivers that are using special priority levels. - - If in doubt, say N. - -config INTC_BALANCING - bool "Hardware IRQ balancing support" - depends on SMP && SUPERH && CPU_SHX3 - help - This enables support for IRQ auto-distribution mode on SH-X3 - SMP parts. All of the balancing and CPU wakeup decisions are - taken care of automatically by hardware for distributed - vectors. - - If in doubt, say N. - -config INTC_MAPPING_DEBUG - bool "Expose IRQ to per-controller id mapping via debugfs" - depends on DEBUG_FS - help - This will create a debugfs entry for showing the relationship - between system IRQs and the per-controller id tables. - - If in doubt, say N. - -endif diff --git a/drivers/sh/intc/Makefile b/drivers/sh/intc/Makefile deleted file mode 100644 index bdd855327e41d5..00000000000000 --- a/drivers/sh/intc/Makefile +++ /dev/null @@ -1,6 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-only -obj-y := access.o chip.o core.o handle.o irqdomain.o virq.o - -obj-$(CONFIG_INTC_BALANCING) += balancing.o -obj-$(CONFIG_INTC_USERIMASK) += userimask.o -obj-$(CONFIG_INTC_MAPPING_DEBUG) += virq-debugfs.o diff --git a/drivers/sh/intc/access.c b/drivers/sh/intc/access.c deleted file mode 100644 index 114390f967d26e..00000000000000 --- a/drivers/sh/intc/access.c +++ /dev/null @@ -1,246 +0,0 @@ -/* - * Common INTC2 register accessors - * - * Copyright (C) 2007, 2008 Magnus Damm - * Copyright (C) 2009, 2010 Paul Mundt - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - */ -#include -#include "internals.h" - -unsigned long intc_phys_to_virt(struct intc_desc_int *d, unsigned long address) -{ - struct intc_window *window; - int k; - - /* scan through physical windows and convert address */ - for (k = 0; k < d->nr_windows; k++) { - window = d->window + k; - - if (address < window->phys) - continue; - - if (address >= (window->phys + window->size)) - continue; - - address -= window->phys; - address += (unsigned long)window->virt; - - return address; - } - - /* no windows defined, register must be 1:1 mapped virt:phys */ - return address; -} - -unsigned int intc_get_reg(struct intc_desc_int *d, unsigned long address) -{ - unsigned int k; - - address = intc_phys_to_virt(d, address); - - for (k = 0; k < d->nr_reg; k++) { - if (d->reg[k] == address) - return k; - } - - BUG(); - return 0; -} - -unsigned int intc_set_field_from_handle(unsigned int value, - unsigned int field_value, - unsigned int handle) -{ - unsigned int width = _INTC_WIDTH(handle); - unsigned int shift = _INTC_SHIFT(handle); - - value &= ~(((1 << width) - 1) << shift); - value |= field_value << shift; - return value; -} - -unsigned long intc_get_field_from_handle(unsigned int value, unsigned int handle) -{ - unsigned int width = _INTC_WIDTH(handle); - unsigned int shift = _INTC_SHIFT(handle); - unsigned int mask = ((1 << width) - 1) << shift; - - return (value & mask) >> shift; -} - -static unsigned long test_8(unsigned long addr, unsigned long h, - unsigned long ignore) -{ - void __iomem *ptr = (void __iomem *)addr; - return intc_get_field_from_handle(__raw_readb(ptr), h); -} - -static unsigned long test_16(unsigned long addr, unsigned long h, - unsigned long ignore) -{ - void __iomem *ptr = (void __iomem *)addr; - return intc_get_field_from_handle(__raw_readw(ptr), h); -} - -static unsigned long test_32(unsigned long addr, unsigned long h, - unsigned long ignore) -{ - void __iomem *ptr = (void __iomem *)addr; - return intc_get_field_from_handle(__raw_readl(ptr), h); -} - -static unsigned long write_8(unsigned long addr, unsigned long h, - unsigned long data) -{ - void __iomem *ptr = (void __iomem *)addr; - __raw_writeb(intc_set_field_from_handle(0, data, h), ptr); - (void)__raw_readb(ptr); /* Defeat write posting */ - return 0; -} - -static unsigned long write_16(unsigned long addr, unsigned long h, - unsigned long data) -{ - void __iomem *ptr = (void __iomem *)addr; - __raw_writew(intc_set_field_from_handle(0, data, h), ptr); - (void)__raw_readw(ptr); /* Defeat write posting */ - return 0; -} - -static unsigned long write_32(unsigned long addr, unsigned long h, - unsigned long data) -{ - void __iomem *ptr = (void __iomem *)addr; - __raw_writel(intc_set_field_from_handle(0, data, h), ptr); - (void)__raw_readl(ptr); /* Defeat write posting */ - return 0; -} - -static unsigned long modify_8(unsigned long addr, unsigned long h, - unsigned long data) -{ - void __iomem *ptr = (void __iomem *)addr; - unsigned long flags; - unsigned int value; - local_irq_save(flags); - value = intc_set_field_from_handle(__raw_readb(ptr), data, h); - __raw_writeb(value, ptr); - (void)__raw_readb(ptr); /* Defeat write posting */ - local_irq_restore(flags); - return 0; -} - -static unsigned long modify_16(unsigned long addr, unsigned long h, - unsigned long data) -{ - void __iomem *ptr = (void __iomem *)addr; - unsigned long flags; - unsigned int value; - local_irq_save(flags); - value = intc_set_field_from_handle(__raw_readw(ptr), data, h); - __raw_writew(value, ptr); - (void)__raw_readw(ptr); /* Defeat write posting */ - local_irq_restore(flags); - return 0; -} - -static unsigned long modify_32(unsigned long addr, unsigned long h, - unsigned long data) -{ - void __iomem *ptr = (void __iomem *)addr; - unsigned long flags; - unsigned int value; - local_irq_save(flags); - value = intc_set_field_from_handle(__raw_readl(ptr), data, h); - __raw_writel(value, ptr); - (void)__raw_readl(ptr); /* Defeat write posting */ - local_irq_restore(flags); - return 0; -} - -static unsigned long intc_mode_field(unsigned long addr, - unsigned long handle, - unsigned long (*fn)(unsigned long, - unsigned long, - unsigned long), - unsigned int irq) -{ - return fn(addr, handle, ((1 << _INTC_WIDTH(handle)) - 1)); -} - -static unsigned long intc_mode_zero(unsigned long addr, - unsigned long handle, - unsigned long (*fn)(unsigned long, - unsigned long, - unsigned long), - unsigned int irq) -{ - return fn(addr, handle, 0); -} - -static unsigned long intc_mode_prio(unsigned long addr, - unsigned long handle, - unsigned long (*fn)(unsigned long, - unsigned long, - unsigned long), - unsigned int irq) -{ - return fn(addr, handle, intc_get_prio_level(irq)); -} - -unsigned long (*intc_reg_fns[])(unsigned long addr, - unsigned long h, - unsigned long data) = { - [REG_FN_TEST_BASE + 0] = test_8, - [REG_FN_TEST_BASE + 1] = test_16, - [REG_FN_TEST_BASE + 3] = test_32, - [REG_FN_WRITE_BASE + 0] = write_8, - [REG_FN_WRITE_BASE + 1] = write_16, - [REG_FN_WRITE_BASE + 3] = write_32, - [REG_FN_MODIFY_BASE + 0] = modify_8, - [REG_FN_MODIFY_BASE + 1] = modify_16, - [REG_FN_MODIFY_BASE + 3] = modify_32, -}; - -unsigned long (*intc_enable_fns[])(unsigned long addr, - unsigned long handle, - unsigned long (*fn)(unsigned long, - unsigned long, - unsigned long), - unsigned int irq) = { - [MODE_ENABLE_REG] = intc_mode_field, - [MODE_MASK_REG] = intc_mode_zero, - [MODE_DUAL_REG] = intc_mode_field, - [MODE_PRIO_REG] = intc_mode_prio, - [MODE_PCLR_REG] = intc_mode_prio, -}; - -unsigned long (*intc_disable_fns[])(unsigned long addr, - unsigned long handle, - unsigned long (*fn)(unsigned long, - unsigned long, - unsigned long), - unsigned int irq) = { - [MODE_ENABLE_REG] = intc_mode_zero, - [MODE_MASK_REG] = intc_mode_field, - [MODE_DUAL_REG] = intc_mode_field, - [MODE_PRIO_REG] = intc_mode_zero, - [MODE_PCLR_REG] = intc_mode_field, -}; - -unsigned long (*intc_enable_noprio_fns[])(unsigned long addr, - unsigned long handle, - unsigned long (*fn)(unsigned long, - unsigned long, - unsigned long), - unsigned int irq) = { - [MODE_ENABLE_REG] = intc_mode_field, - [MODE_MASK_REG] = intc_mode_zero, - [MODE_DUAL_REG] = intc_mode_field, - [MODE_PRIO_REG] = intc_mode_field, - [MODE_PCLR_REG] = intc_mode_field, -}; diff --git a/drivers/sh/intc/balancing.c b/drivers/sh/intc/balancing.c deleted file mode 100644 index bc780807ccb0fe..00000000000000 --- a/drivers/sh/intc/balancing.c +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Support for hardware-managed IRQ auto-distribution. - * - * Copyright (C) 2010 Paul Mundt - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - */ -#include "internals.h" - -static unsigned long dist_handle[INTC_NR_IRQS]; - -void intc_balancing_enable(unsigned int irq) -{ - struct intc_desc_int *d = get_intc_desc(irq); - unsigned long handle = dist_handle[irq]; - unsigned long addr; - - if (irq_balancing_disabled(irq) || !handle) - return; - - addr = INTC_REG(d, _INTC_ADDR_D(handle), 0); - intc_reg_fns[_INTC_FN(handle)](addr, handle, 1); -} - -void intc_balancing_disable(unsigned int irq) -{ - struct intc_desc_int *d = get_intc_desc(irq); - unsigned long handle = dist_handle[irq]; - unsigned long addr; - - if (irq_balancing_disabled(irq) || !handle) - return; - - addr = INTC_REG(d, _INTC_ADDR_D(handle), 0); - intc_reg_fns[_INTC_FN(handle)](addr, handle, 0); -} - -static unsigned int intc_dist_data(struct intc_desc *desc, - struct intc_desc_int *d, - intc_enum enum_id) -{ - struct intc_mask_reg *mr = desc->hw.mask_regs; - unsigned int i, j, fn, mode; - unsigned long reg_e, reg_d; - - for (i = 0; mr && enum_id && i < desc->hw.nr_mask_regs; i++) { - mr = desc->hw.mask_regs + i; - - /* - * Skip this entry if there's no auto-distribution - * register associated with it. - */ - if (!mr->dist_reg) - continue; - - for (j = 0; j < ARRAY_SIZE(mr->enum_ids); j++) { - if (mr->enum_ids[j] != enum_id) - continue; - - fn = REG_FN_MODIFY_BASE; - mode = MODE_ENABLE_REG; - reg_e = mr->dist_reg; - reg_d = mr->dist_reg; - - fn += (mr->reg_width >> 3) - 1; - return _INTC_MK(fn, mode, - intc_get_reg(d, reg_e), - intc_get_reg(d, reg_d), - 1, - (mr->reg_width - 1) - j); - } - } - - /* - * It's possible we've gotten here with no distribution options - * available for the IRQ in question, so we just skip over those. - */ - return 0; -} - -void intc_set_dist_handle(unsigned int irq, struct intc_desc *desc, - struct intc_desc_int *d, intc_enum id) -{ - unsigned long flags; - - /* - * Nothing to do for this IRQ. - */ - if (!desc->hw.mask_regs) - return; - - raw_spin_lock_irqsave(&intc_big_lock, flags); - dist_handle[irq] = intc_dist_data(desc, d, id); - raw_spin_unlock_irqrestore(&intc_big_lock, flags); -} diff --git a/drivers/sh/intc/chip.c b/drivers/sh/intc/chip.c deleted file mode 100644 index 828d81e02b37ab..00000000000000 --- a/drivers/sh/intc/chip.c +++ /dev/null @@ -1,211 +0,0 @@ -/* - * IRQ chip definitions for INTC IRQs. - * - * Copyright (C) 2007, 2008 Magnus Damm - * Copyright (C) 2009 - 2012 Paul Mundt - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - */ -#include -#include -#include -#include "internals.h" - -void _intc_enable(struct irq_data *data, unsigned long handle) -{ - unsigned int irq = data->irq; - struct intc_desc_int *d = get_intc_desc(irq); - unsigned long addr; - unsigned int cpu; - - for (cpu = 0; cpu < SMP_NR(d, _INTC_ADDR_E(handle)); cpu++) { -#ifdef CONFIG_SMP - if (!cpumask_test_cpu(cpu, irq_data_get_affinity_mask(data))) - continue; -#endif - addr = INTC_REG(d, _INTC_ADDR_E(handle), cpu); - intc_enable_fns[_INTC_MODE(handle)](addr, handle, intc_reg_fns\ - [_INTC_FN(handle)], irq); - } - - intc_balancing_enable(irq); -} - -static void intc_enable(struct irq_data *data) -{ - _intc_enable(data, (unsigned long)irq_data_get_irq_chip_data(data)); -} - -static void intc_disable(struct irq_data *data) -{ - unsigned int irq = data->irq; - struct intc_desc_int *d = get_intc_desc(irq); - unsigned long handle = (unsigned long)irq_data_get_irq_chip_data(data); - unsigned long addr; - unsigned int cpu; - - intc_balancing_disable(irq); - - for (cpu = 0; cpu < SMP_NR(d, _INTC_ADDR_D(handle)); cpu++) { -#ifdef CONFIG_SMP - if (!cpumask_test_cpu(cpu, irq_data_get_affinity_mask(data))) - continue; -#endif - addr = INTC_REG(d, _INTC_ADDR_D(handle), cpu); - intc_disable_fns[_INTC_MODE(handle)](addr, handle,intc_reg_fns\ - [_INTC_FN(handle)], irq); - } -} - -#ifdef CONFIG_SMP -/* - * This is held with the irq desc lock held, so we don't require any - * additional locking here at the intc desc level. The affinity mask is - * later tested in the enable/disable paths. - */ -static int intc_set_affinity(struct irq_data *data, - const struct cpumask *cpumask, - bool force) -{ - if (!cpumask_intersects(cpumask, cpu_online_mask)) - return -1; - - irq_data_update_affinity(data, cpumask); - - return IRQ_SET_MASK_OK_NOCOPY; -} -#endif - -static void intc_mask_ack(struct irq_data *data) -{ - unsigned int irq = data->irq; - struct intc_desc_int *d = get_intc_desc(irq); - unsigned long handle = intc_get_ack_handle(irq); - void __iomem *addr; - - intc_disable(data); - - /* read register and write zero only to the associated bit */ - if (handle) { - unsigned int value; - - addr = (void __iomem *)INTC_REG(d, _INTC_ADDR_D(handle), 0); - value = intc_set_field_from_handle(0, 1, handle); - - switch (_INTC_FN(handle)) { - case REG_FN_MODIFY_BASE + 0: /* 8bit */ - __raw_readb(addr); - __raw_writeb(0xff ^ value, addr); - break; - case REG_FN_MODIFY_BASE + 1: /* 16bit */ - __raw_readw(addr); - __raw_writew(0xffff ^ value, addr); - break; - case REG_FN_MODIFY_BASE + 3: /* 32bit */ - __raw_readl(addr); - __raw_writel(0xffffffff ^ value, addr); - break; - default: - BUG(); - break; - } - } -} - -static struct intc_handle_int *intc_find_irq(struct intc_handle_int *hp, - unsigned int nr_hp, - unsigned int irq) -{ - struct intc_handle_int key; - - key.irq = irq; - key.handle = 0; - - return bsearch(&key, hp, nr_hp, sizeof(*hp), intc_handle_int_cmp); -} - -int intc_set_priority(unsigned int irq, unsigned int prio) -{ - struct intc_desc_int *d = get_intc_desc(irq); - struct irq_data *data = irq_get_irq_data(irq); - struct intc_handle_int *ihp; - - if (!intc_get_prio_level(irq) || prio <= 1) - return -EINVAL; - - ihp = intc_find_irq(d->prio, d->nr_prio, irq); - if (ihp) { - if (prio >= (1 << _INTC_WIDTH(ihp->handle))) - return -EINVAL; - - intc_set_prio_level(irq, prio); - - /* - * only set secondary masking method directly - * primary masking method is using intc_prio_level[irq] - * priority level will be set during next enable() - */ - if (_INTC_FN(ihp->handle) != REG_FN_ERR) - _intc_enable(data, ihp->handle); - } - return 0; -} - -#define SENSE_VALID_FLAG 0x80 -#define VALID(x) (x | SENSE_VALID_FLAG) - -static unsigned char intc_irq_sense_table[IRQ_TYPE_SENSE_MASK + 1] = { - [IRQ_TYPE_EDGE_FALLING] = VALID(0), - [IRQ_TYPE_EDGE_RISING] = VALID(1), - [IRQ_TYPE_LEVEL_LOW] = VALID(2), - /* SH7706, SH7707 and SH7709 do not support high level triggered */ -#if !defined(CONFIG_CPU_SUBTYPE_SH7706) && \ - !defined(CONFIG_CPU_SUBTYPE_SH7707) && \ - !defined(CONFIG_CPU_SUBTYPE_SH7709) - [IRQ_TYPE_LEVEL_HIGH] = VALID(3), -#endif -#if defined(CONFIG_ARM) /* all recent SH-Mobile / R-Mobile ARM support this */ - [IRQ_TYPE_EDGE_BOTH] = VALID(4), -#endif -}; - -static int intc_set_type(struct irq_data *data, unsigned int type) -{ - unsigned int irq = data->irq; - struct intc_desc_int *d = get_intc_desc(irq); - unsigned char value = intc_irq_sense_table[type & IRQ_TYPE_SENSE_MASK]; - struct intc_handle_int *ihp; - unsigned long addr; - - if (!value) - return -EINVAL; - - value &= ~SENSE_VALID_FLAG; - - ihp = intc_find_irq(d->sense, d->nr_sense, irq); - if (ihp) { - /* PINT has 2-bit sense registers, should fail on EDGE_BOTH */ - if (value >= (1 << _INTC_WIDTH(ihp->handle))) - return -EINVAL; - - addr = INTC_REG(d, _INTC_ADDR_E(ihp->handle), 0); - intc_reg_fns[_INTC_FN(ihp->handle)](addr, ihp->handle, value); - } - - return 0; -} - -struct irq_chip intc_irq_chip = { - .irq_mask = intc_disable, - .irq_unmask = intc_enable, - .irq_mask_ack = intc_mask_ack, - .irq_enable = intc_enable, - .irq_disable = intc_disable, - .irq_set_type = intc_set_type, -#ifdef CONFIG_SMP - .irq_set_affinity = intc_set_affinity, -#endif - .flags = IRQCHIP_SKIP_SET_WAKE, -}; diff --git a/drivers/sh/intc/core.c b/drivers/sh/intc/core.c deleted file mode 100644 index ca4f4ca413f11d..00000000000000 --- a/drivers/sh/intc/core.c +++ /dev/null @@ -1,501 +0,0 @@ -/* - * Shared interrupt handling code for IPR and INTC2 types of IRQs. - * - * Copyright (C) 2007, 2008 Magnus Damm - * Copyright (C) 2009 - 2012 Paul Mundt - * - * Based on intc2.c and ipr.c - * - * Copyright (C) 1999 Niibe Yutaka & Takeshi Yaegashi - * Copyright (C) 2000 Kazumoto Kojima - * Copyright (C) 2001 David J. Mckay (david.mckay@st.com) - * Copyright (C) 2003 Takashi Kusuda - * Copyright (C) 2005, 2006 Paul Mundt - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - */ -#define pr_fmt(fmt) "intc: " fmt - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "internals.h" - -LIST_HEAD(intc_list); -DEFINE_RAW_SPINLOCK(intc_big_lock); -static unsigned int nr_intc_controllers; - -/* - * Default priority level - * - this needs to be at least 2 for 5-bit priorities on 7780 - */ -static unsigned int default_prio_level = 2; /* 2 - 16 */ -static unsigned int intc_prio_level[INTC_NR_IRQS]; /* for now */ - -unsigned int intc_get_dfl_prio_level(void) -{ - return default_prio_level; -} - -unsigned int intc_get_prio_level(unsigned int irq) -{ - return intc_prio_level[irq]; -} - -void intc_set_prio_level(unsigned int irq, unsigned int level) -{ - unsigned long flags; - - raw_spin_lock_irqsave(&intc_big_lock, flags); - intc_prio_level[irq] = level; - raw_spin_unlock_irqrestore(&intc_big_lock, flags); -} - -static void intc_redirect_irq(struct irq_desc *desc) -{ - generic_handle_irq((unsigned int)irq_desc_get_handler_data(desc)); -} - -static void __init intc_register_irq(struct intc_desc *desc, - struct intc_desc_int *d, - intc_enum enum_id, - unsigned int irq) -{ - struct intc_handle_int *hp; - struct irq_data *irq_data; - unsigned int data[2], primary; - unsigned long flags; - - raw_spin_lock_irqsave(&intc_big_lock, flags); - radix_tree_insert(&d->tree, enum_id, intc_irq_xlate_get(irq)); - raw_spin_unlock_irqrestore(&intc_big_lock, flags); - - /* - * Prefer single interrupt source bitmap over other combinations: - * - * 1. bitmap, single interrupt source - * 2. priority, single interrupt source - * 3. bitmap, multiple interrupt sources (groups) - * 4. priority, multiple interrupt sources (groups) - */ - data[0] = intc_get_mask_handle(desc, d, enum_id, 0); - data[1] = intc_get_prio_handle(desc, d, enum_id, 0); - - primary = 0; - if (!data[0] && data[1]) - primary = 1; - - if (!data[0] && !data[1]) - pr_warn("missing unique irq mask for irq %d (vect 0x%04x)\n", - irq, irq2evt(irq)); - - data[0] = data[0] ? data[0] : intc_get_mask_handle(desc, d, enum_id, 1); - data[1] = data[1] ? data[1] : intc_get_prio_handle(desc, d, enum_id, 1); - - if (!data[primary]) - primary ^= 1; - - BUG_ON(!data[primary]); /* must have primary masking method */ - - irq_data = irq_get_irq_data(irq); - - disable_irq_nosync(irq); - irq_set_chip_and_handler_name(irq, &d->chip, handle_level_irq, - "level"); - irq_set_chip_data(irq, (void *)data[primary]); - - /* - * set priority level - */ - intc_set_prio_level(irq, intc_get_dfl_prio_level()); - - /* enable secondary masking method if present */ - if (data[!primary]) - _intc_enable(irq_data, data[!primary]); - - /* add irq to d->prio list if priority is available */ - if (data[1]) { - hp = d->prio + d->nr_prio; - hp->irq = irq; - hp->handle = data[1]; - - if (primary) { - /* - * only secondary priority should access registers, so - * set _INTC_FN(h) = REG_FN_ERR for intc_set_priority() - */ - hp->handle &= ~_INTC_MK(0x0f, 0, 0, 0, 0, 0); - hp->handle |= _INTC_MK(REG_FN_ERR, 0, 0, 0, 0, 0); - } - d->nr_prio++; - } - - /* add irq to d->sense list if sense is available */ - data[0] = intc_get_sense_handle(desc, d, enum_id); - if (data[0]) { - (d->sense + d->nr_sense)->irq = irq; - (d->sense + d->nr_sense)->handle = data[0]; - d->nr_sense++; - } - - /* irq should be disabled by default */ - d->chip.irq_mask(irq_data); - - intc_set_ack_handle(irq, desc, d, enum_id); - intc_set_dist_handle(irq, desc, d, enum_id); - - activate_irq(irq); -} - -static unsigned int __init save_reg(struct intc_desc_int *d, - unsigned int cnt, - unsigned long value, - unsigned int smp) -{ - if (value) { - value = intc_phys_to_virt(d, value); - - d->reg[cnt] = value; -#ifdef CONFIG_SMP - d->smp[cnt] = smp; -#endif - return 1; - } - - return 0; -} - -static bool __init intc_map(struct irq_domain *domain, int irq) -{ - if (!irq_to_desc(irq) && irq_alloc_desc_at(irq, NUMA_NO_NODE) != irq) { - pr_err("uname to allocate IRQ %d\n", irq); - return false; - } - - if (irq_domain_associate(domain, irq, irq)) { - pr_err("domain association failure\n"); - return false; - } - - return true; -} - -int __init register_intc_controller(struct intc_desc *desc) -{ - unsigned int i, k, smp; - struct intc_hw_desc *hw = &desc->hw; - struct intc_desc_int *d; - struct resource *res; - - pr_info("Registered controller '%s' with %u IRQs\n", - desc->name, hw->nr_vectors); - - d = kzalloc(sizeof(*d), GFP_NOWAIT); - if (!d) - goto err0; - - INIT_LIST_HEAD(&d->list); - list_add_tail(&d->list, &intc_list); - - raw_spin_lock_init(&d->lock); - INIT_RADIX_TREE(&d->tree, GFP_ATOMIC); - - d->index = nr_intc_controllers; - - if (desc->num_resources) { - d->nr_windows = desc->num_resources; - d->window = kcalloc(d->nr_windows, sizeof(*d->window), - GFP_NOWAIT); - if (!d->window) - goto err1; - - for (k = 0; k < d->nr_windows; k++) { - res = desc->resource + k; - WARN_ON(resource_type(res) != IORESOURCE_MEM); - d->window[k].phys = res->start; - d->window[k].size = resource_size(res); - d->window[k].virt = ioremap(res->start, - resource_size(res)); - if (!d->window[k].virt) - goto err2; - } - } - - d->nr_reg = hw->mask_regs ? hw->nr_mask_regs * 2 : 0; -#ifdef CONFIG_INTC_BALANCING - if (d->nr_reg) - d->nr_reg += hw->nr_mask_regs; -#endif - d->nr_reg += hw->prio_regs ? hw->nr_prio_regs * 2 : 0; - d->nr_reg += hw->sense_regs ? hw->nr_sense_regs : 0; - d->nr_reg += hw->ack_regs ? hw->nr_ack_regs : 0; - d->nr_reg += hw->subgroups ? hw->nr_subgroups : 0; - - d->reg = kcalloc(d->nr_reg, sizeof(*d->reg), GFP_NOWAIT); - if (!d->reg) - goto err2; - -#ifdef CONFIG_SMP - d->smp = kcalloc(d->nr_reg, sizeof(*d->smp), GFP_NOWAIT); - if (!d->smp) - goto err3; -#endif - k = 0; - - if (hw->mask_regs) { - for (i = 0; i < hw->nr_mask_regs; i++) { - smp = IS_SMP(hw->mask_regs[i]); - k += save_reg(d, k, hw->mask_regs[i].set_reg, smp); - k += save_reg(d, k, hw->mask_regs[i].clr_reg, smp); -#ifdef CONFIG_INTC_BALANCING - k += save_reg(d, k, hw->mask_regs[i].dist_reg, 0); -#endif - } - } - - if (hw->prio_regs) { - d->prio = kcalloc(hw->nr_vectors, sizeof(*d->prio), - GFP_NOWAIT); - if (!d->prio) - goto err4; - - for (i = 0; i < hw->nr_prio_regs; i++) { - smp = IS_SMP(hw->prio_regs[i]); - k += save_reg(d, k, hw->prio_regs[i].set_reg, smp); - k += save_reg(d, k, hw->prio_regs[i].clr_reg, smp); - } - - sort(d->prio, hw->nr_prio_regs, sizeof(*d->prio), - intc_handle_int_cmp, NULL); - } - - if (hw->sense_regs) { - d->sense = kcalloc(hw->nr_vectors, sizeof(*d->sense), - GFP_NOWAIT); - if (!d->sense) - goto err5; - - for (i = 0; i < hw->nr_sense_regs; i++) - k += save_reg(d, k, hw->sense_regs[i].reg, 0); - - sort(d->sense, hw->nr_sense_regs, sizeof(*d->sense), - intc_handle_int_cmp, NULL); - } - - if (hw->subgroups) - for (i = 0; i < hw->nr_subgroups; i++) - if (hw->subgroups[i].reg) - k+= save_reg(d, k, hw->subgroups[i].reg, 0); - - memcpy(&d->chip, &intc_irq_chip, sizeof(struct irq_chip)); - d->chip.name = desc->name; - - if (hw->ack_regs) - for (i = 0; i < hw->nr_ack_regs; i++) - k += save_reg(d, k, hw->ack_regs[i].set_reg, 0); - else - d->chip.irq_mask_ack = d->chip.irq_disable; - - /* disable bits matching force_disable before registering irqs */ - if (desc->force_disable) - intc_enable_disable_enum(desc, d, desc->force_disable, 0); - - /* disable bits matching force_enable before registering irqs */ - if (desc->force_enable) - intc_enable_disable_enum(desc, d, desc->force_enable, 0); - - BUG_ON(k > 256); /* _INTC_ADDR_E() and _INTC_ADDR_D() are 8 bits */ - - intc_irq_domain_init(d, hw); - - /* register the vectors one by one */ - for (i = 0; i < hw->nr_vectors; i++) { - struct intc_vect *vect = hw->vectors + i; - unsigned int irq = evt2irq(vect->vect); - - if (!vect->enum_id) - continue; - - if (!intc_map(d->domain, irq)) - continue; - - intc_irq_xlate_set(irq, vect->enum_id, d); - intc_register_irq(desc, d, vect->enum_id, irq); - - for (k = i + 1; k < hw->nr_vectors; k++) { - struct intc_vect *vect2 = hw->vectors + k; - unsigned int irq2 = evt2irq(vect2->vect); - - if (vect->enum_id != vect2->enum_id) - continue; - - /* - * In the case of multi-evt handling and sparse - * IRQ support, each vector still needs to have - * its own backing irq_desc. - */ - if (!intc_map(d->domain, irq2)) - continue; - - vect2->enum_id = 0; - - /* redirect this interrupts to the first one */ - irq_set_chip(irq2, &dummy_irq_chip); - irq_set_chained_handler_and_data(irq2, - intc_redirect_irq, - (void *)irq); - } - } - - intc_subgroup_init(desc, d); - - /* enable bits matching force_enable after registering irqs */ - if (desc->force_enable) - intc_enable_disable_enum(desc, d, desc->force_enable, 1); - - d->skip_suspend = desc->skip_syscore_suspend; - - nr_intc_controllers++; - - return 0; -err5: - kfree(d->prio); -err4: -#ifdef CONFIG_SMP - kfree(d->smp); -err3: -#endif - kfree(d->reg); -err2: - for (k = 0; k < d->nr_windows; k++) - if (d->window[k].virt) - iounmap(d->window[k].virt); - - kfree(d->window); -err1: - kfree(d); -err0: - pr_err("unable to allocate INTC memory\n"); - - return -ENOMEM; -} - -static int intc_suspend(void) -{ - struct intc_desc_int *d; - - list_for_each_entry(d, &intc_list, list) { - int irq; - - if (d->skip_suspend) - continue; - - /* enable wakeup irqs belonging to this intc controller */ - for_each_active_irq(irq) { - struct irq_data *data; - struct irq_chip *chip; - - data = irq_get_irq_data(irq); - chip = irq_data_get_irq_chip(data); - if (chip != &d->chip) - continue; - if (irqd_is_wakeup_set(data)) - chip->irq_enable(data); - } - } - return 0; -} - -static void intc_resume(void) -{ - struct intc_desc_int *d; - - list_for_each_entry(d, &intc_list, list) { - int irq; - - if (d->skip_suspend) - continue; - - for_each_active_irq(irq) { - struct irq_data *data; - struct irq_chip *chip; - - data = irq_get_irq_data(irq); - chip = irq_data_get_irq_chip(data); - /* - * This will catch the redirect and VIRQ cases - * due to the dummy_irq_chip being inserted. - */ - if (chip != &d->chip) - continue; - if (irqd_irq_disabled(data)) - chip->irq_disable(data); - else - chip->irq_enable(data); - } - } -} - -struct syscore_ops intc_syscore_ops = { - .suspend = intc_suspend, - .resume = intc_resume, -}; - -struct bus_type intc_subsys = { - .name = "intc", - .dev_name = "intc", -}; - -static ssize_t -show_intc_name(struct device *dev, struct device_attribute *attr, char *buf) -{ - struct intc_desc_int *d; - - d = container_of(dev, struct intc_desc_int, dev); - - return sprintf(buf, "%s\n", d->chip.name); -} - -static DEVICE_ATTR(name, S_IRUGO, show_intc_name, NULL); - -static int __init register_intc_devs(void) -{ - struct intc_desc_int *d; - int error; - - register_syscore_ops(&intc_syscore_ops); - - error = subsys_system_register(&intc_subsys, NULL); - if (!error) { - list_for_each_entry(d, &intc_list, list) { - d->dev.id = d->index; - d->dev.bus = &intc_subsys; - error = device_register(&d->dev); - if (error == 0) - error = device_create_file(&d->dev, - &dev_attr_name); - if (error) - break; - } - } - - if (error) - pr_err("device registration error\n"); - - return error; -} -device_initcall(register_intc_devs); diff --git a/drivers/sh/intc/handle.c b/drivers/sh/intc/handle.c deleted file mode 100644 index 7863a44918a293..00000000000000 --- a/drivers/sh/intc/handle.c +++ /dev/null @@ -1,306 +0,0 @@ -/* - * Shared interrupt handling code for IPR and INTC2 types of IRQs. - * - * Copyright (C) 2007, 2008 Magnus Damm - * Copyright (C) 2009, 2010 Paul Mundt - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - */ -#include -#include -#include -#include "internals.h" - -static unsigned long ack_handle[INTC_NR_IRQS]; - -static intc_enum __init intc_grp_id(struct intc_desc *desc, - intc_enum enum_id) -{ - struct intc_group *g = desc->hw.groups; - unsigned int i, j; - - for (i = 0; g && enum_id && i < desc->hw.nr_groups; i++) { - g = desc->hw.groups + i; - - for (j = 0; g->enum_ids[j]; j++) { - if (g->enum_ids[j] != enum_id) - continue; - - return g->enum_id; - } - } - - return 0; -} - -static unsigned int __init _intc_mask_data(struct intc_desc *desc, - struct intc_desc_int *d, - intc_enum enum_id, - unsigned int *reg_idx, - unsigned int *fld_idx) -{ - struct intc_mask_reg *mr = desc->hw.mask_regs; - unsigned int fn, mode; - unsigned long reg_e, reg_d; - - while (mr && enum_id && *reg_idx < desc->hw.nr_mask_regs) { - mr = desc->hw.mask_regs + *reg_idx; - - for (; *fld_idx < ARRAY_SIZE(mr->enum_ids); (*fld_idx)++) { - if (mr->enum_ids[*fld_idx] != enum_id) - continue; - - if (mr->set_reg && mr->clr_reg) { - fn = REG_FN_WRITE_BASE; - mode = MODE_DUAL_REG; - reg_e = mr->clr_reg; - reg_d = mr->set_reg; - } else { - fn = REG_FN_MODIFY_BASE; - if (mr->set_reg) { - mode = MODE_ENABLE_REG; - reg_e = mr->set_reg; - reg_d = mr->set_reg; - } else { - mode = MODE_MASK_REG; - reg_e = mr->clr_reg; - reg_d = mr->clr_reg; - } - } - - fn += (mr->reg_width >> 3) - 1; - return _INTC_MK(fn, mode, - intc_get_reg(d, reg_e), - intc_get_reg(d, reg_d), - 1, - (mr->reg_width - 1) - *fld_idx); - } - - *fld_idx = 0; - (*reg_idx)++; - } - - return 0; -} - -unsigned int __init -intc_get_mask_handle(struct intc_desc *desc, struct intc_desc_int *d, - intc_enum enum_id, int do_grps) -{ - unsigned int i = 0; - unsigned int j = 0; - unsigned int ret; - - ret = _intc_mask_data(desc, d, enum_id, &i, &j); - if (ret) - return ret; - - if (do_grps) - return intc_get_mask_handle(desc, d, intc_grp_id(desc, enum_id), 0); - - return 0; -} - -static unsigned int __init _intc_prio_data(struct intc_desc *desc, - struct intc_desc_int *d, - intc_enum enum_id, - unsigned int *reg_idx, - unsigned int *fld_idx) -{ - struct intc_prio_reg *pr = desc->hw.prio_regs; - unsigned int fn, n, mode, bit; - unsigned long reg_e, reg_d; - - while (pr && enum_id && *reg_idx < desc->hw.nr_prio_regs) { - pr = desc->hw.prio_regs + *reg_idx; - - for (; *fld_idx < ARRAY_SIZE(pr->enum_ids); (*fld_idx)++) { - if (pr->enum_ids[*fld_idx] != enum_id) - continue; - - if (pr->set_reg && pr->clr_reg) { - fn = REG_FN_WRITE_BASE; - mode = MODE_PCLR_REG; - reg_e = pr->set_reg; - reg_d = pr->clr_reg; - } else { - fn = REG_FN_MODIFY_BASE; - mode = MODE_PRIO_REG; - if (!pr->set_reg) - BUG(); - reg_e = pr->set_reg; - reg_d = pr->set_reg; - } - - fn += (pr->reg_width >> 3) - 1; - n = *fld_idx + 1; - - BUG_ON(n * pr->field_width > pr->reg_width); - - bit = pr->reg_width - (n * pr->field_width); - - return _INTC_MK(fn, mode, - intc_get_reg(d, reg_e), - intc_get_reg(d, reg_d), - pr->field_width, bit); - } - - *fld_idx = 0; - (*reg_idx)++; - } - - return 0; -} - -unsigned int __init -intc_get_prio_handle(struct intc_desc *desc, struct intc_desc_int *d, - intc_enum enum_id, int do_grps) -{ - unsigned int i = 0; - unsigned int j = 0; - unsigned int ret; - - ret = _intc_prio_data(desc, d, enum_id, &i, &j); - if (ret) - return ret; - - if (do_grps) - return intc_get_prio_handle(desc, d, intc_grp_id(desc, enum_id), 0); - - return 0; -} - -static unsigned int intc_ack_data(struct intc_desc *desc, - struct intc_desc_int *d, intc_enum enum_id) -{ - struct intc_mask_reg *mr = desc->hw.ack_regs; - unsigned int i, j, fn, mode; - unsigned long reg_e, reg_d; - - for (i = 0; mr && enum_id && i < desc->hw.nr_ack_regs; i++) { - mr = desc->hw.ack_regs + i; - - for (j = 0; j < ARRAY_SIZE(mr->enum_ids); j++) { - if (mr->enum_ids[j] != enum_id) - continue; - - fn = REG_FN_MODIFY_BASE; - mode = MODE_ENABLE_REG; - reg_e = mr->set_reg; - reg_d = mr->set_reg; - - fn += (mr->reg_width >> 3) - 1; - return _INTC_MK(fn, mode, - intc_get_reg(d, reg_e), - intc_get_reg(d, reg_d), - 1, - (mr->reg_width - 1) - j); - } - } - - return 0; -} - -static void intc_enable_disable(struct intc_desc_int *d, - unsigned long handle, int do_enable) -{ - unsigned long addr; - unsigned int cpu; - unsigned long (*fn)(unsigned long, unsigned long, - unsigned long (*)(unsigned long, unsigned long, - unsigned long), - unsigned int); - - if (do_enable) { - for (cpu = 0; cpu < SMP_NR(d, _INTC_ADDR_E(handle)); cpu++) { - addr = INTC_REG(d, _INTC_ADDR_E(handle), cpu); - fn = intc_enable_noprio_fns[_INTC_MODE(handle)]; - fn(addr, handle, intc_reg_fns[_INTC_FN(handle)], 0); - } - } else { - for (cpu = 0; cpu < SMP_NR(d, _INTC_ADDR_D(handle)); cpu++) { - addr = INTC_REG(d, _INTC_ADDR_D(handle), cpu); - fn = intc_disable_fns[_INTC_MODE(handle)]; - fn(addr, handle, intc_reg_fns[_INTC_FN(handle)], 0); - } - } -} - -void __init intc_enable_disable_enum(struct intc_desc *desc, - struct intc_desc_int *d, - intc_enum enum_id, int enable) -{ - unsigned int i, j, data; - - /* go through and enable/disable all mask bits */ - i = j = 0; - do { - data = _intc_mask_data(desc, d, enum_id, &i, &j); - if (data) - intc_enable_disable(d, data, enable); - j++; - } while (data); - - /* go through and enable/disable all priority fields */ - i = j = 0; - do { - data = _intc_prio_data(desc, d, enum_id, &i, &j); - if (data) - intc_enable_disable(d, data, enable); - - j++; - } while (data); -} - -unsigned int __init -intc_get_sense_handle(struct intc_desc *desc, struct intc_desc_int *d, - intc_enum enum_id) -{ - struct intc_sense_reg *sr = desc->hw.sense_regs; - unsigned int i, j, fn, bit; - - for (i = 0; sr && enum_id && i < desc->hw.nr_sense_regs; i++) { - sr = desc->hw.sense_regs + i; - - for (j = 0; j < ARRAY_SIZE(sr->enum_ids); j++) { - if (sr->enum_ids[j] != enum_id) - continue; - - fn = REG_FN_MODIFY_BASE; - fn += (sr->reg_width >> 3) - 1; - - BUG_ON((j + 1) * sr->field_width > sr->reg_width); - - bit = sr->reg_width - ((j + 1) * sr->field_width); - - return _INTC_MK(fn, 0, intc_get_reg(d, sr->reg), - 0, sr->field_width, bit); - } - } - - return 0; -} - - -void intc_set_ack_handle(unsigned int irq, struct intc_desc *desc, - struct intc_desc_int *d, intc_enum id) -{ - unsigned long flags; - - /* - * Nothing to do for this IRQ. - */ - if (!desc->hw.ack_regs) - return; - - raw_spin_lock_irqsave(&intc_big_lock, flags); - ack_handle[irq] = intc_ack_data(desc, d, id); - raw_spin_unlock_irqrestore(&intc_big_lock, flags); -} - -unsigned long intc_get_ack_handle(unsigned int irq) -{ - return ack_handle[irq]; -} diff --git a/drivers/sh/intc/internals.h b/drivers/sh/intc/internals.h deleted file mode 100644 index fa73c173b56a60..00000000000000 --- a/drivers/sh/intc/internals.h +++ /dev/null @@ -1,191 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -#include -#include -#include -#include -#include -#include -#include -#include - -#define _INTC_MK(fn, mode, addr_e, addr_d, width, shift) \ - ((shift) | ((width) << 5) | ((fn) << 9) | ((mode) << 13) | \ - ((addr_e) << 16) | ((addr_d << 24))) - -#define _INTC_SHIFT(h) (h & 0x1f) -#define _INTC_WIDTH(h) ((h >> 5) & 0xf) -#define _INTC_FN(h) ((h >> 9) & 0xf) -#define _INTC_MODE(h) ((h >> 13) & 0x7) -#define _INTC_ADDR_E(h) ((h >> 16) & 0xff) -#define _INTC_ADDR_D(h) ((h >> 24) & 0xff) - -#ifdef CONFIG_SMP -#define IS_SMP(x) (x.smp) -#define INTC_REG(d, x, c) (d->reg[(x)] + ((d->smp[(x)] & 0xff) * c)) -#define SMP_NR(d, x) ((d->smp[(x)] >> 8) ? (d->smp[(x)] >> 8) : 1) -#else -#define IS_SMP(x) 0 -#define INTC_REG(d, x, c) (d->reg[(x)]) -#define SMP_NR(d, x) 1 -#endif - -struct intc_handle_int { - unsigned int irq; - unsigned long handle; -}; - -struct intc_window { - phys_addr_t phys; - void __iomem *virt; - unsigned long size; -}; - -struct intc_map_entry { - intc_enum enum_id; - struct intc_desc_int *desc; -}; - -struct intc_subgroup_entry { - unsigned int pirq; - intc_enum enum_id; - unsigned long handle; -}; - -struct intc_desc_int { - struct list_head list; - struct device dev; - struct radix_tree_root tree; - raw_spinlock_t lock; - unsigned int index; - unsigned long *reg; -#ifdef CONFIG_SMP - unsigned long *smp; -#endif - unsigned int nr_reg; - struct intc_handle_int *prio; - unsigned int nr_prio; - struct intc_handle_int *sense; - unsigned int nr_sense; - struct intc_window *window; - unsigned int nr_windows; - struct irq_domain *domain; - struct irq_chip chip; - bool skip_suspend; -}; - - -enum { - REG_FN_ERR = 0, - REG_FN_TEST_BASE = 1, - REG_FN_WRITE_BASE = 5, - REG_FN_MODIFY_BASE = 9 -}; - -enum { MODE_ENABLE_REG = 0, /* Bit(s) set -> interrupt enabled */ - MODE_MASK_REG, /* Bit(s) set -> interrupt disabled */ - MODE_DUAL_REG, /* Two registers, set bit to enable / disable */ - MODE_PRIO_REG, /* Priority value written to enable interrupt */ - MODE_PCLR_REG, /* Above plus all bits set to disable interrupt */ -}; - -static inline struct intc_desc_int *get_intc_desc(unsigned int irq) -{ - struct irq_chip *chip = irq_get_chip(irq); - - return container_of(chip, struct intc_desc_int, chip); -} - -/* - * Grumble. - */ -static inline void activate_irq(int irq) -{ - irq_modify_status(irq, IRQ_NOREQUEST, IRQ_NOPROBE); -} - -static inline int intc_handle_int_cmp(const void *a, const void *b) -{ - const struct intc_handle_int *_a = a; - const struct intc_handle_int *_b = b; - - return _a->irq - _b->irq; -} - -/* access.c */ -extern unsigned long -(*intc_reg_fns[])(unsigned long addr, unsigned long h, unsigned long data); - -extern unsigned long -(*intc_enable_fns[])(unsigned long addr, unsigned long handle, - unsigned long (*fn)(unsigned long, - unsigned long, unsigned long), - unsigned int irq); -extern unsigned long -(*intc_disable_fns[])(unsigned long addr, unsigned long handle, - unsigned long (*fn)(unsigned long, - unsigned long, unsigned long), - unsigned int irq); -extern unsigned long -(*intc_enable_noprio_fns[])(unsigned long addr, unsigned long handle, - unsigned long (*fn)(unsigned long, - unsigned long, unsigned long), - unsigned int irq); - -unsigned long intc_phys_to_virt(struct intc_desc_int *d, unsigned long address); -unsigned int intc_get_reg(struct intc_desc_int *d, unsigned long address); -unsigned int intc_set_field_from_handle(unsigned int value, - unsigned int field_value, - unsigned int handle); -unsigned long intc_get_field_from_handle(unsigned int value, - unsigned int handle); - -/* balancing.c */ -#ifdef CONFIG_INTC_BALANCING -void intc_balancing_enable(unsigned int irq); -void intc_balancing_disable(unsigned int irq); -void intc_set_dist_handle(unsigned int irq, struct intc_desc *desc, - struct intc_desc_int *d, intc_enum id); -#else -static inline void intc_balancing_enable(unsigned int irq) { } -static inline void intc_balancing_disable(unsigned int irq) { } -static inline void -intc_set_dist_handle(unsigned int irq, struct intc_desc *desc, - struct intc_desc_int *d, intc_enum id) { } -#endif - -/* chip.c */ -extern struct irq_chip intc_irq_chip; -void _intc_enable(struct irq_data *data, unsigned long handle); - -/* core.c */ -extern struct list_head intc_list; -extern raw_spinlock_t intc_big_lock; -extern struct bus_type intc_subsys; - -unsigned int intc_get_dfl_prio_level(void); -unsigned int intc_get_prio_level(unsigned int irq); -void intc_set_prio_level(unsigned int irq, unsigned int level); - -/* handle.c */ -unsigned int intc_get_mask_handle(struct intc_desc *desc, - struct intc_desc_int *d, - intc_enum enum_id, int do_grps); -unsigned int intc_get_prio_handle(struct intc_desc *desc, - struct intc_desc_int *d, - intc_enum enum_id, int do_grps); -unsigned int intc_get_sense_handle(struct intc_desc *desc, - struct intc_desc_int *d, - intc_enum enum_id); -void intc_set_ack_handle(unsigned int irq, struct intc_desc *desc, - struct intc_desc_int *d, intc_enum id); -unsigned long intc_get_ack_handle(unsigned int irq); -void intc_enable_disable_enum(struct intc_desc *desc, struct intc_desc_int *d, - intc_enum enum_id, int enable); - -/* irqdomain.c */ -void intc_irq_domain_init(struct intc_desc_int *d, struct intc_hw_desc *hw); - -/* virq.c */ -void intc_subgroup_init(struct intc_desc *desc, struct intc_desc_int *d); -void intc_irq_xlate_set(unsigned int irq, intc_enum id, struct intc_desc_int *d); -struct intc_map_entry *intc_irq_xlate_get(unsigned int irq); diff --git a/drivers/sh/intc/irqdomain.c b/drivers/sh/intc/irqdomain.c deleted file mode 100644 index 3968f1c3c5c308..00000000000000 --- a/drivers/sh/intc/irqdomain.c +++ /dev/null @@ -1,68 +0,0 @@ -/* - * IRQ domain support for SH INTC subsystem - * - * Copyright (C) 2012 Paul Mundt - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - */ -#define pr_fmt(fmt) "intc: " fmt - -#include -#include -#include -#include "internals.h" - -/** - * intc_irq_domain_evt_xlate() - Generic xlate for vectored IRQs. - * - * This takes care of exception vector to hwirq translation through - * by way of evt2irq() translation. - * - * Note: For platforms that use a flat vector space without INTEVT this - * basically just mimics irq_domain_xlate_onecell() by way of a nopped - * out evt2irq() implementation. - */ -static int intc_evt_xlate(struct irq_domain *d, struct device_node *ctrlr, - const u32 *intspec, unsigned int intsize, - unsigned long *out_hwirq, unsigned int *out_type) -{ - if (WARN_ON(intsize < 1)) - return -EINVAL; - - *out_hwirq = evt2irq(intspec[0]); - *out_type = IRQ_TYPE_NONE; - - return 0; -} - -static const struct irq_domain_ops intc_evt_ops = { - .xlate = intc_evt_xlate, -}; - -void __init intc_irq_domain_init(struct intc_desc_int *d, - struct intc_hw_desc *hw) -{ - unsigned int irq_base, irq_end; - - /* - * Quick linear revmap check - */ - irq_base = evt2irq(hw->vectors[0].vect); - irq_end = evt2irq(hw->vectors[hw->nr_vectors - 1].vect); - - /* - * Linear domains have a hard-wired assertion that IRQs start at - * 0 in order to make some performance optimizations. Lamely - * restrict the linear case to these conditions here, taking the - * tree penalty for linear cases with non-zero hwirq bases. - */ - if (irq_base == 0 && irq_end == (irq_base + hw->nr_vectors - 1)) - d->domain = irq_domain_add_linear(NULL, hw->nr_vectors, - &intc_evt_ops, NULL); - else - d->domain = irq_domain_add_tree(NULL, &intc_evt_ops, NULL); - - BUG_ON(!d->domain); -} diff --git a/drivers/sh/intc/userimask.c b/drivers/sh/intc/userimask.c deleted file mode 100644 index f9f043a3d90a23..00000000000000 --- a/drivers/sh/intc/userimask.c +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Support for hardware-assisted userspace interrupt masking. - * - * Copyright (C) 2010 Paul Mundt - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - */ -#define pr_fmt(fmt) "intc: " fmt - -#include -#include -#include -#include -#include -#include -#include "internals.h" - -static void __iomem *uimask; - -static ssize_t -show_intc_userimask(struct device *dev, - struct device_attribute *attr, char *buf) -{ - return sprintf(buf, "%d\n", (__raw_readl(uimask) >> 4) & 0xf); -} - -static ssize_t -store_intc_userimask(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - unsigned long level; - - level = simple_strtoul(buf, NULL, 10); - - /* - * Minimal acceptable IRQ levels are in the 2 - 16 range, but - * these are chomped so as to not interfere with normal IRQs. - * - * Level 1 is a special case on some CPUs in that it's not - * directly settable, but given that USERIMASK cuts off below a - * certain level, we don't care about this limitation here. - * Level 0 on the other hand equates to user masking disabled. - * - * We use the default priority level as a cut off so that only - * special case opt-in IRQs can be mangled. - */ - if (level >= intc_get_dfl_prio_level()) - return -EINVAL; - - __raw_writel(0xa5 << 24 | level << 4, uimask); - - return count; -} - -static DEVICE_ATTR(userimask, S_IRUSR | S_IWUSR, - show_intc_userimask, store_intc_userimask); - - -static int __init userimask_sysdev_init(void) -{ - if (unlikely(!uimask)) - return -ENXIO; - - return device_create_file(intc_subsys.dev_root, &dev_attr_userimask); -} -late_initcall(userimask_sysdev_init); - -int register_intc_userimask(unsigned long addr) -{ - if (unlikely(uimask)) - return -EBUSY; - - uimask = ioremap(addr, SZ_4K); - if (unlikely(!uimask)) - return -ENOMEM; - - pr_info("userimask support registered for levels 0 -> %d\n", - intc_get_dfl_prio_level() - 1); - - return 0; -} diff --git a/drivers/sh/intc/virq-debugfs.c b/drivers/sh/intc/virq-debugfs.c deleted file mode 100644 index 939915a07d9997..00000000000000 --- a/drivers/sh/intc/virq-debugfs.c +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Support for virtual IRQ subgroups debugfs mapping. - * - * Copyright (C) 2010 Paul Mundt - * - * Modelled after arch/powerpc/kernel/irq.c. - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - */ -#include -#include -#include -#include -#include -#include "internals.h" - -static int intc_irq_xlate_show(struct seq_file *m, void *priv) -{ - int i; - - seq_printf(m, "%-5s %-7s %-15s\n", "irq", "enum", "chip name"); - - for (i = 1; i < nr_irqs; i++) { - struct intc_map_entry *entry = intc_irq_xlate_get(i); - struct intc_desc_int *desc = entry->desc; - - if (!desc) - continue; - - seq_printf(m, "%5d ", i); - seq_printf(m, "0x%05x ", entry->enum_id); - seq_printf(m, "%-15s\n", desc->chip.name); - } - - return 0; -} - -DEFINE_SHOW_ATTRIBUTE(intc_irq_xlate); - -static int __init intc_irq_xlate_init(void) -{ - /* - * XXX.. use arch_debugfs_dir here when all of the intc users are - * converted. - */ - if (debugfs_create_file("intc_irq_xlate", S_IRUGO, NULL, NULL, - &intc_irq_xlate_fops) == NULL) - return -ENOMEM; - - return 0; -} -fs_initcall(intc_irq_xlate_init); diff --git a/drivers/sh/intc/virq.c b/drivers/sh/intc/virq.c deleted file mode 100644 index a638c3048207c0..00000000000000 --- a/drivers/sh/intc/virq.c +++ /dev/null @@ -1,269 +0,0 @@ -/* - * Support for virtual IRQ subgroups. - * - * Copyright (C) 2010 Paul Mundt - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - */ -#define pr_fmt(fmt) "intc: " fmt - -#include -#include -#include -#include -#include -#include -#include "internals.h" - -static struct intc_map_entry intc_irq_xlate[INTC_NR_IRQS]; - -struct intc_virq_list { - unsigned int irq; - struct intc_virq_list *next; -}; - -#define for_each_virq(entry, head) \ - for (entry = head; entry; entry = entry->next) - -/* - * Tags for the radix tree - */ -#define INTC_TAG_VIRQ_NEEDS_ALLOC 0 - -void intc_irq_xlate_set(unsigned int irq, intc_enum id, struct intc_desc_int *d) -{ - unsigned long flags; - - raw_spin_lock_irqsave(&intc_big_lock, flags); - intc_irq_xlate[irq].enum_id = id; - intc_irq_xlate[irq].desc = d; - raw_spin_unlock_irqrestore(&intc_big_lock, flags); -} - -struct intc_map_entry *intc_irq_xlate_get(unsigned int irq) -{ - return intc_irq_xlate + irq; -} - -int intc_irq_lookup(const char *chipname, intc_enum enum_id) -{ - struct intc_map_entry *ptr; - struct intc_desc_int *d; - int irq = -1; - - list_for_each_entry(d, &intc_list, list) { - int tagged; - - if (strcmp(d->chip.name, chipname) != 0) - continue; - - /* - * Catch early lookups for subgroup VIRQs that have not - * yet been allocated an IRQ. This already includes a - * fast-path out if the tree is untagged, so there is no - * need to explicitly test the root tree. - */ - tagged = radix_tree_tag_get(&d->tree, enum_id, - INTC_TAG_VIRQ_NEEDS_ALLOC); - if (unlikely(tagged)) - break; - - ptr = radix_tree_lookup(&d->tree, enum_id); - if (ptr) { - irq = ptr - intc_irq_xlate; - break; - } - } - - return irq; -} -EXPORT_SYMBOL_GPL(intc_irq_lookup); - -static int add_virq_to_pirq(unsigned int irq, unsigned int virq) -{ - struct intc_virq_list *entry; - struct intc_virq_list **last = NULL; - - /* scan for duplicates */ - for_each_virq(entry, irq_get_handler_data(irq)) { - if (entry->irq == virq) - return 0; - last = &entry->next; - } - - entry = kzalloc(sizeof(struct intc_virq_list), GFP_ATOMIC); - if (!entry) - return -ENOMEM; - - entry->irq = virq; - - if (last) - *last = entry; - else - irq_set_handler_data(irq, entry); - - return 0; -} - -static void intc_virq_handler(struct irq_desc *desc) -{ - unsigned int irq = irq_desc_get_irq(desc); - struct irq_data *data = irq_desc_get_irq_data(desc); - struct irq_chip *chip = irq_data_get_irq_chip(data); - struct intc_virq_list *entry, *vlist = irq_data_get_irq_handler_data(data); - struct intc_desc_int *d = get_intc_desc(irq); - - chip->irq_mask_ack(data); - - for_each_virq(entry, vlist) { - unsigned long addr, handle; - struct irq_desc *vdesc = irq_to_desc(entry->irq); - - if (vdesc) { - handle = (unsigned long)irq_desc_get_handler_data(vdesc); - addr = INTC_REG(d, _INTC_ADDR_E(handle), 0); - if (intc_reg_fns[_INTC_FN(handle)](addr, handle, 0)) - generic_handle_irq_desc(vdesc); - } - } - - chip->irq_unmask(data); -} - -static unsigned long __init intc_subgroup_data(struct intc_subgroup *subgroup, - struct intc_desc_int *d, - unsigned int index) -{ - unsigned int fn = REG_FN_TEST_BASE + (subgroup->reg_width >> 3) - 1; - - return _INTC_MK(fn, MODE_ENABLE_REG, intc_get_reg(d, subgroup->reg), - 0, 1, (subgroup->reg_width - 1) - index); -} - -static void __init intc_subgroup_init_one(struct intc_desc *desc, - struct intc_desc_int *d, - struct intc_subgroup *subgroup) -{ - struct intc_map_entry *mapped; - unsigned int pirq; - unsigned long flags; - int i; - - mapped = radix_tree_lookup(&d->tree, subgroup->parent_id); - if (!mapped) { - WARN_ON(1); - return; - } - - pirq = mapped - intc_irq_xlate; - - raw_spin_lock_irqsave(&d->lock, flags); - - for (i = 0; i < ARRAY_SIZE(subgroup->enum_ids); i++) { - struct intc_subgroup_entry *entry; - int err; - - if (!subgroup->enum_ids[i]) - continue; - - entry = kmalloc(sizeof(*entry), GFP_NOWAIT); - if (!entry) - break; - - entry->pirq = pirq; - entry->enum_id = subgroup->enum_ids[i]; - entry->handle = intc_subgroup_data(subgroup, d, i); - - err = radix_tree_insert(&d->tree, entry->enum_id, entry); - if (unlikely(err < 0)) - break; - - radix_tree_tag_set(&d->tree, entry->enum_id, - INTC_TAG_VIRQ_NEEDS_ALLOC); - } - - raw_spin_unlock_irqrestore(&d->lock, flags); -} - -void __init intc_subgroup_init(struct intc_desc *desc, struct intc_desc_int *d) -{ - int i; - - if (!desc->hw.subgroups) - return; - - for (i = 0; i < desc->hw.nr_subgroups; i++) - intc_subgroup_init_one(desc, d, desc->hw.subgroups + i); -} - -static void __init intc_subgroup_map(struct intc_desc_int *d) -{ - struct intc_subgroup_entry *entries[32]; - unsigned long flags; - unsigned int nr_found; - int i; - - raw_spin_lock_irqsave(&d->lock, flags); - -restart: - nr_found = radix_tree_gang_lookup_tag_slot(&d->tree, - (void ***)entries, 0, ARRAY_SIZE(entries), - INTC_TAG_VIRQ_NEEDS_ALLOC); - - for (i = 0; i < nr_found; i++) { - struct intc_subgroup_entry *entry; - int irq; - - entry = radix_tree_deref_slot((void **)entries[i]); - if (unlikely(!entry)) - continue; - if (radix_tree_deref_retry(entry)) - goto restart; - - irq = irq_alloc_desc(numa_node_id()); - if (unlikely(irq < 0)) { - pr_err("no more free IRQs, bailing..\n"); - break; - } - - activate_irq(irq); - - pr_info("Setting up a chained VIRQ from %d -> %d\n", - irq, entry->pirq); - - intc_irq_xlate_set(irq, entry->enum_id, d); - - irq_set_chip_and_handler_name(irq, irq_get_chip(entry->pirq), - handle_simple_irq, "virq"); - irq_set_chip_data(irq, irq_get_chip_data(entry->pirq)); - - irq_set_handler_data(irq, (void *)entry->handle); - - /* - * Set the virtual IRQ as non-threadable. - */ - irq_set_nothread(irq); - - /* Set handler data before installing the handler */ - add_virq_to_pirq(entry->pirq, irq); - irq_set_chained_handler(entry->pirq, intc_virq_handler); - - radix_tree_tag_clear(&d->tree, entry->enum_id, - INTC_TAG_VIRQ_NEEDS_ALLOC); - radix_tree_replace_slot(&d->tree, (void **)entries[i], - &intc_irq_xlate[irq]); - } - - raw_spin_unlock_irqrestore(&d->lock, flags); -} - -void __init intc_finalize(void) -{ - struct intc_desc_int *d; - - list_for_each_entry(d, &intc_list, list) - if (radix_tree_tagged(&d->tree, INTC_TAG_VIRQ_NEEDS_ALLOC)) - intc_subgroup_map(d); -} diff --git a/drivers/sh/maple/Makefile b/drivers/sh/maple/Makefile deleted file mode 100644 index c3a80910c212ce..00000000000000 --- a/drivers/sh/maple/Makefile +++ /dev/null @@ -1,4 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-only -# Makefile for Maple Bus - -obj-$(CONFIG_MAPLE) := maple.o diff --git a/drivers/sh/maple/maple.c b/drivers/sh/maple/maple.c deleted file mode 100644 index e24e220e56eea1..00000000000000 --- a/drivers/sh/maple/maple.c +++ /dev/null @@ -1,895 +0,0 @@ -/* - * Core maple bus functionality - * - * Copyright (C) 2007 - 2009 Adrian McMenamin - * Copyright (C) 2001 - 2008 Paul Mundt - * Copyright (C) 2000 - 2001 YAEGASHI Takeshi - * Copyright (C) 2001 M. R. Brown - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -MODULE_AUTHOR("Adrian McMenamin "); -MODULE_DESCRIPTION("Maple bus driver for Dreamcast"); -MODULE_LICENSE("GPL v2"); - -static void maple_dma_handler(struct work_struct *work); -static void maple_vblank_handler(struct work_struct *work); - -static DECLARE_WORK(maple_dma_process, maple_dma_handler); -static DECLARE_WORK(maple_vblank_process, maple_vblank_handler); - -static LIST_HEAD(maple_waitq); -static LIST_HEAD(maple_sentq); - -/* mutex to protect queue of waiting packets */ -static DEFINE_MUTEX(maple_wlist_lock); - -static struct maple_driver maple_unsupported_device; -static struct device maple_bus; -static int subdevice_map[MAPLE_PORTS]; -static unsigned long *maple_sendbuf, *maple_sendptr, *maple_lastptr; -static unsigned long maple_pnp_time; -static int started, scanning, fullscan; -static struct kmem_cache *maple_queue_cache; - -struct maple_device_specify { - int port; - int unit; -}; - -static bool checked[MAPLE_PORTS]; -static bool empty[MAPLE_PORTS]; -static struct maple_device *baseunits[MAPLE_PORTS]; - -/** - * maple_driver_register - register a maple driver - * @drv: maple driver to be registered. - * - * Registers the passed in @drv, while updating the bus type. - * Devices with matching function IDs will be automatically probed. - */ -int maple_driver_register(struct maple_driver *drv) -{ - if (!drv) - return -EINVAL; - - drv->drv.bus = &maple_bus_type; - - return driver_register(&drv->drv); -} -EXPORT_SYMBOL_GPL(maple_driver_register); - -/** - * maple_driver_unregister - unregister a maple driver. - * @drv: maple driver to unregister. - * - * Cleans up after maple_driver_register(). To be invoked in the exit - * path of any module drivers. - */ -void maple_driver_unregister(struct maple_driver *drv) -{ - driver_unregister(&drv->drv); -} -EXPORT_SYMBOL_GPL(maple_driver_unregister); - -/* set hardware registers to enable next round of dma */ -static void maple_dma_reset(void) -{ - __raw_writel(MAPLE_MAGIC, MAPLE_RESET); - /* set trig type to 0 for software trigger, 1 for hardware (VBLANK) */ - __raw_writel(1, MAPLE_TRIGTYPE); - /* - * Maple system register - * bits 31 - 16 timeout in units of 20nsec - * bit 12 hard trigger - set 0 to keep responding to VBLANK - * bits 9 - 8 set 00 for 2 Mbps, 01 for 1 Mbps - * bits 3 - 0 delay (in 1.3ms) between VBLANK and start of DMA - * max delay is 11 - */ - __raw_writel(MAPLE_2MBPS | MAPLE_TIMEOUT(0xFFFF), MAPLE_SPEED); - __raw_writel(virt_to_phys(maple_sendbuf), MAPLE_DMAADDR); - __raw_writel(1, MAPLE_ENABLE); -} - -/** - * maple_getcond_callback - setup handling MAPLE_COMMAND_GETCOND - * @dev: device responding - * @callback: handler callback - * @interval: interval in jiffies between callbacks - * @function: the function code for the device - */ -void maple_getcond_callback(struct maple_device *dev, - void (*callback) (struct mapleq *mq), - unsigned long interval, unsigned long function) -{ - dev->callback = callback; - dev->interval = interval; - dev->function = cpu_to_be32(function); - dev->when = jiffies; -} -EXPORT_SYMBOL_GPL(maple_getcond_callback); - -static int maple_dma_done(void) -{ - return (__raw_readl(MAPLE_STATE) & 1) == 0; -} - -static void maple_release_device(struct device *dev) -{ - struct maple_device *mdev; - struct mapleq *mq; - - mdev = to_maple_dev(dev); - mq = mdev->mq; - kmem_cache_free(maple_queue_cache, mq->recvbuf); - kfree(mq); - kfree(mdev); -} - -/** - * maple_add_packet - add a single instruction to the maple bus queue - * @mdev: maple device - * @function: function on device being queried - * @command: maple command to add - * @length: length of command string (in 32 bit words) - * @data: remainder of command string - */ -int maple_add_packet(struct maple_device *mdev, u32 function, u32 command, - size_t length, void *data) -{ - int ret = 0; - void *sendbuf = NULL; - - if (length) { - sendbuf = kcalloc(length, 4, GFP_KERNEL); - if (!sendbuf) { - ret = -ENOMEM; - goto out; - } - ((__be32 *)sendbuf)[0] = cpu_to_be32(function); - } - - mdev->mq->command = command; - mdev->mq->length = length; - if (length > 1) - memcpy(sendbuf + 4, data, (length - 1) * 4); - mdev->mq->sendbuf = sendbuf; - - mutex_lock(&maple_wlist_lock); - list_add_tail(&mdev->mq->list, &maple_waitq); - mutex_unlock(&maple_wlist_lock); -out: - return ret; -} -EXPORT_SYMBOL_GPL(maple_add_packet); - -static struct mapleq *maple_allocq(struct maple_device *mdev) -{ - struct mapleq *mq; - - mq = kzalloc(sizeof(*mq), GFP_KERNEL); - if (!mq) - goto failed_nomem; - - INIT_LIST_HEAD(&mq->list); - mq->dev = mdev; - mq->recvbuf = kmem_cache_zalloc(maple_queue_cache, GFP_KERNEL); - if (!mq->recvbuf) - goto failed_p2; - mq->recvbuf->buf = &((mq->recvbuf->bufx)[0]); - - return mq; - -failed_p2: - kfree(mq); -failed_nomem: - dev_err(&mdev->dev, "could not allocate memory for device (%d, %d)\n", - mdev->port, mdev->unit); - return NULL; -} - -static struct maple_device *maple_alloc_dev(int port, int unit) -{ - struct maple_device *mdev; - - /* zero this out to avoid kobj subsystem - * thinking it has already been registered */ - - mdev = kzalloc(sizeof(*mdev), GFP_KERNEL); - if (!mdev) - return NULL; - - mdev->port = port; - mdev->unit = unit; - - mdev->mq = maple_allocq(mdev); - - if (!mdev->mq) { - kfree(mdev); - return NULL; - } - mdev->dev.bus = &maple_bus_type; - mdev->dev.parent = &maple_bus; - init_waitqueue_head(&mdev->maple_wait); - return mdev; -} - -static void maple_free_dev(struct maple_device *mdev) -{ - kmem_cache_free(maple_queue_cache, mdev->mq->recvbuf); - kfree(mdev->mq); - kfree(mdev); -} - -/* process the command queue into a maple command block - * terminating command has bit 32 of first long set to 0 - */ -static void maple_build_block(struct mapleq *mq) -{ - int port, unit, from, to, len; - unsigned long *lsendbuf = mq->sendbuf; - - port = mq->dev->port & 3; - unit = mq->dev->unit; - len = mq->length; - from = port << 6; - to = (port << 6) | (unit > 0 ? (1 << (unit - 1)) & 0x1f : 0x20); - - *maple_lastptr &= 0x7fffffff; - maple_lastptr = maple_sendptr; - - *maple_sendptr++ = (port << 16) | len | 0x80000000; - *maple_sendptr++ = virt_to_phys(mq->recvbuf->buf); - *maple_sendptr++ = - mq->command | (to << 8) | (from << 16) | (len << 24); - while (len-- > 0) - *maple_sendptr++ = *lsendbuf++; -} - -/* build up command queue */ -static void maple_send(void) -{ - int i, maple_packets = 0; - struct mapleq *mq, *nmq; - - if (!maple_dma_done()) - return; - - /* disable DMA */ - __raw_writel(0, MAPLE_ENABLE); - - if (!list_empty(&maple_sentq)) - goto finish; - - mutex_lock(&maple_wlist_lock); - if (list_empty(&maple_waitq)) { - mutex_unlock(&maple_wlist_lock); - goto finish; - } - - maple_lastptr = maple_sendbuf; - maple_sendptr = maple_sendbuf; - - list_for_each_entry_safe(mq, nmq, &maple_waitq, list) { - maple_build_block(mq); - list_del_init(&mq->list); - list_add_tail(&mq->list, &maple_sentq); - if (maple_packets++ > MAPLE_MAXPACKETS) - break; - } - mutex_unlock(&maple_wlist_lock); - if (maple_packets > 0) { - for (i = 0; i < (1 << MAPLE_DMA_PAGES); i++) - __flush_purge_region(maple_sendbuf + i * PAGE_SIZE, - PAGE_SIZE); - } - -finish: - maple_dma_reset(); -} - -/* check if there is a driver registered likely to match this device */ -static int maple_check_matching_driver(struct device_driver *driver, - void *devptr) -{ - struct maple_driver *maple_drv; - struct maple_device *mdev; - - mdev = devptr; - maple_drv = to_maple_driver(driver); - if (mdev->devinfo.function & cpu_to_be32(maple_drv->function)) - return 1; - return 0; -} - -static void maple_detach_driver(struct maple_device *mdev) -{ - device_unregister(&mdev->dev); -} - -/* process initial MAPLE_COMMAND_DEVINFO for each device or port */ -static void maple_attach_driver(struct maple_device *mdev) -{ - char *p, *recvbuf; - unsigned long function; - int matched, error; - - recvbuf = mdev->mq->recvbuf->buf; - /* copy the data as individual elements in - * case of memory optimisation */ - memcpy(&mdev->devinfo.function, recvbuf + 4, 4); - memcpy(&mdev->devinfo.function_data[0], recvbuf + 8, 12); - memcpy(&mdev->devinfo.area_code, recvbuf + 20, 1); - memcpy(&mdev->devinfo.connector_direction, recvbuf + 21, 1); - memcpy(&mdev->devinfo.product_name[0], recvbuf + 22, 30); - memcpy(&mdev->devinfo.standby_power, recvbuf + 112, 2); - memcpy(&mdev->devinfo.max_power, recvbuf + 114, 2); - memcpy(mdev->product_name, mdev->devinfo.product_name, 30); - mdev->product_name[30] = '\0'; - memcpy(mdev->product_licence, mdev->devinfo.product_licence, 60); - mdev->product_licence[60] = '\0'; - - for (p = mdev->product_name + 29; mdev->product_name <= p; p--) - if (*p == ' ') - *p = '\0'; - else - break; - for (p = mdev->product_licence + 59; mdev->product_licence <= p; p--) - if (*p == ' ') - *p = '\0'; - else - break; - - function = be32_to_cpu(mdev->devinfo.function); - - dev_info(&mdev->dev, "detected %s: function 0x%lX: at (%d, %d)\n", - mdev->product_name, function, mdev->port, mdev->unit); - - if (function > 0x200) { - /* Do this silently - as not a real device */ - function = 0; - mdev->driver = &maple_unsupported_device; - dev_set_name(&mdev->dev, "%d:0.port", mdev->port); - } else { - matched = - bus_for_each_drv(&maple_bus_type, NULL, mdev, - maple_check_matching_driver); - - if (matched == 0) { - /* Driver does not exist yet */ - dev_info(&mdev->dev, "no driver found\n"); - mdev->driver = &maple_unsupported_device; - } - dev_set_name(&mdev->dev, "%d:0%d.%lX", mdev->port, - mdev->unit, function); - } - - mdev->function = function; - mdev->dev.release = &maple_release_device; - - atomic_set(&mdev->busy, 0); - error = device_register(&mdev->dev); - if (error) { - dev_warn(&mdev->dev, "could not register device at" - " (%d, %d), with error 0x%X\n", mdev->unit, - mdev->port, error); - maple_free_dev(mdev); - mdev = NULL; - return; - } -} - -/* - * if device has been registered for the given - * port and unit then return 1 - allows identification - * of which devices need to be attached or detached - */ -static int check_maple_device(struct device *device, void *portptr) -{ - struct maple_device_specify *ds; - struct maple_device *mdev; - - ds = portptr; - mdev = to_maple_dev(device); - if (mdev->port == ds->port && mdev->unit == ds->unit) - return 1; - return 0; -} - -static int setup_maple_commands(struct device *device, void *ignored) -{ - int add; - struct maple_device *mdev = to_maple_dev(device); - if (mdev->interval > 0 && atomic_read(&mdev->busy) == 0 && - time_after(jiffies, mdev->when)) { - /* bounce if we cannot add */ - add = maple_add_packet(mdev, - be32_to_cpu(mdev->devinfo.function), - MAPLE_COMMAND_GETCOND, 1, NULL); - if (!add) - mdev->when = jiffies + mdev->interval; - } else { - if (time_after(jiffies, maple_pnp_time)) - /* Ensure we don't have block reads and devinfo - * calls interfering with one another - so flag the - * device as busy */ - if (atomic_read(&mdev->busy) == 0) { - atomic_set(&mdev->busy, 1); - maple_add_packet(mdev, 0, - MAPLE_COMMAND_DEVINFO, 0, NULL); - } - } - return 0; -} - -/* VBLANK bottom half - implemented via workqueue */ -static void maple_vblank_handler(struct work_struct *work) -{ - int x, locking; - struct maple_device *mdev; - - if (!maple_dma_done()) - return; - - __raw_writel(0, MAPLE_ENABLE); - - if (!list_empty(&maple_sentq)) - goto finish; - - /* - * Set up essential commands - to fetch data and - * check devices are still present - */ - bus_for_each_dev(&maple_bus_type, NULL, NULL, - setup_maple_commands); - - if (time_after(jiffies, maple_pnp_time)) { - /* - * Scan the empty ports - bus is flakey and may have - * mis-reported emptyness - */ - for (x = 0; x < MAPLE_PORTS; x++) { - if (checked[x] && empty[x]) { - mdev = baseunits[x]; - if (!mdev) - break; - atomic_set(&mdev->busy, 1); - locking = maple_add_packet(mdev, 0, - MAPLE_COMMAND_DEVINFO, 0, NULL); - if (!locking) - break; - } - } - - maple_pnp_time = jiffies + MAPLE_PNP_INTERVAL; - } - -finish: - maple_send(); -} - -/* handle devices added via hotplugs - placing them on queue for DEVINFO */ -static void maple_map_subunits(struct maple_device *mdev, int submask) -{ - int retval, k, devcheck; - struct maple_device *mdev_add; - struct maple_device_specify ds; - - ds.port = mdev->port; - for (k = 0; k < 5; k++) { - ds.unit = k + 1; - retval = - bus_for_each_dev(&maple_bus_type, NULL, &ds, - check_maple_device); - if (retval) { - submask = submask >> 1; - continue; - } - devcheck = submask & 0x01; - if (devcheck) { - mdev_add = maple_alloc_dev(mdev->port, k + 1); - if (!mdev_add) - return; - atomic_set(&mdev_add->busy, 1); - maple_add_packet(mdev_add, 0, MAPLE_COMMAND_DEVINFO, - 0, NULL); - /* mark that we are checking sub devices */ - scanning = 1; - } - submask = submask >> 1; - } -} - -/* mark a device as removed */ -static void maple_clean_submap(struct maple_device *mdev) -{ - int killbit; - - killbit = (mdev->unit > 0 ? (1 << (mdev->unit - 1)) & 0x1f : 0x20); - killbit = ~killbit; - killbit &= 0xFF; - subdevice_map[mdev->port] = subdevice_map[mdev->port] & killbit; -} - -/* handle empty port or hotplug removal */ -static void maple_response_none(struct maple_device *mdev) -{ - maple_clean_submap(mdev); - - if (likely(mdev->unit != 0)) { - /* - * Block devices play up - * and give the impression they have - * been removed even when still in place or - * trip the mtd layer when they have - * really gone - this code traps that eventuality - * and ensures we aren't overloaded with useless - * error messages - */ - if (mdev->can_unload) { - if (!mdev->can_unload(mdev)) { - atomic_set(&mdev->busy, 2); - wake_up(&mdev->maple_wait); - return; - } - } - - dev_info(&mdev->dev, "detaching device at (%d, %d)\n", - mdev->port, mdev->unit); - maple_detach_driver(mdev); - return; - } else { - if (!started || !fullscan) { - if (checked[mdev->port] == false) { - checked[mdev->port] = true; - empty[mdev->port] = true; - dev_info(&mdev->dev, "no devices" - " to port %d\n", mdev->port); - } - return; - } - } - /* Some hardware devices generate false detach messages on unit 0 */ - atomic_set(&mdev->busy, 0); -} - -/* preprocess hotplugs or scans */ -static void maple_response_devinfo(struct maple_device *mdev, - char *recvbuf) -{ - char submask; - if (!started || (scanning == 2) || !fullscan) { - if ((mdev->unit == 0) && (checked[mdev->port] == false)) { - checked[mdev->port] = true; - maple_attach_driver(mdev); - } else { - if (mdev->unit != 0) - maple_attach_driver(mdev); - if (mdev->unit == 0) { - empty[mdev->port] = false; - maple_attach_driver(mdev); - } - } - } - if (mdev->unit == 0) { - submask = recvbuf[2] & 0x1F; - if (submask ^ subdevice_map[mdev->port]) { - maple_map_subunits(mdev, submask); - subdevice_map[mdev->port] = submask; - } - } -} - -static void maple_response_fileerr(struct maple_device *mdev, void *recvbuf) -{ - if (mdev->fileerr_handler) { - mdev->fileerr_handler(mdev, recvbuf); - return; - } else - dev_warn(&mdev->dev, "device at (%d, %d) reports" - "file error 0x%X\n", mdev->port, mdev->unit, - ((int *)recvbuf)[1]); -} - -static void maple_port_rescan(void) -{ - int i; - struct maple_device *mdev; - - fullscan = 1; - for (i = 0; i < MAPLE_PORTS; i++) { - if (checked[i] == false) { - fullscan = 0; - mdev = baseunits[i]; - maple_add_packet(mdev, 0, MAPLE_COMMAND_DEVINFO, - 0, NULL); - } - } -} - -/* maple dma end bottom half - implemented via workqueue */ -static void maple_dma_handler(struct work_struct *work) -{ - struct mapleq *mq, *nmq; - struct maple_device *mdev; - char *recvbuf; - enum maple_code code; - - if (!maple_dma_done()) - return; - __raw_writel(0, MAPLE_ENABLE); - if (!list_empty(&maple_sentq)) { - list_for_each_entry_safe(mq, nmq, &maple_sentq, list) { - mdev = mq->dev; - recvbuf = mq->recvbuf->buf; - __flush_invalidate_region(sh_cacheop_vaddr(recvbuf), - 0x400); - code = recvbuf[0]; - kfree(mq->sendbuf); - list_del_init(&mq->list); - switch (code) { - case MAPLE_RESPONSE_NONE: - maple_response_none(mdev); - break; - - case MAPLE_RESPONSE_DEVINFO: - maple_response_devinfo(mdev, recvbuf); - atomic_set(&mdev->busy, 0); - break; - - case MAPLE_RESPONSE_DATATRF: - if (mdev->callback) - mdev->callback(mq); - atomic_set(&mdev->busy, 0); - wake_up(&mdev->maple_wait); - break; - - case MAPLE_RESPONSE_FILEERR: - maple_response_fileerr(mdev, recvbuf); - atomic_set(&mdev->busy, 0); - wake_up(&mdev->maple_wait); - break; - - case MAPLE_RESPONSE_AGAIN: - case MAPLE_RESPONSE_BADCMD: - case MAPLE_RESPONSE_BADFUNC: - dev_warn(&mdev->dev, "non-fatal error" - " 0x%X at (%d, %d)\n", code, - mdev->port, mdev->unit); - atomic_set(&mdev->busy, 0); - break; - - case MAPLE_RESPONSE_ALLINFO: - dev_notice(&mdev->dev, "extended" - " device information request for (%d, %d)" - " but call is not supported\n", mdev->port, - mdev->unit); - atomic_set(&mdev->busy, 0); - break; - - case MAPLE_RESPONSE_OK: - atomic_set(&mdev->busy, 0); - wake_up(&mdev->maple_wait); - break; - - default: - break; - } - } - /* if scanning is 1 then we have subdevices to check */ - if (scanning == 1) { - maple_send(); - scanning = 2; - } else - scanning = 0; - /*check if we have actually tested all ports yet */ - if (!fullscan) - maple_port_rescan(); - /* mark that we have been through the first scan */ - started = 1; - } - maple_send(); -} - -static irqreturn_t maple_dma_interrupt(int irq, void *dev_id) -{ - /* Load everything into the bottom half */ - schedule_work(&maple_dma_process); - return IRQ_HANDLED; -} - -static irqreturn_t maple_vblank_interrupt(int irq, void *dev_id) -{ - schedule_work(&maple_vblank_process); - return IRQ_HANDLED; -} - -static int maple_set_dma_interrupt_handler(void) -{ - return request_irq(HW_EVENT_MAPLE_DMA, maple_dma_interrupt, - IRQF_SHARED, "maple bus DMA", &maple_unsupported_device); -} - -static int maple_set_vblank_interrupt_handler(void) -{ - return request_irq(HW_EVENT_VSYNC, maple_vblank_interrupt, - IRQF_SHARED, "maple bus VBLANK", &maple_unsupported_device); -} - -static int maple_get_dma_buffer(void) -{ - maple_sendbuf = - (void *) __get_free_pages(GFP_KERNEL | __GFP_ZERO, - MAPLE_DMA_PAGES); - if (!maple_sendbuf) - return -ENOMEM; - return 0; -} - -static int maple_match_bus_driver(struct device *devptr, - struct device_driver *drvptr) -{ - struct maple_driver *maple_drv = to_maple_driver(drvptr); - struct maple_device *maple_dev = to_maple_dev(devptr); - - /* Trap empty port case */ - if (maple_dev->devinfo.function == 0xFFFFFFFF) - return 0; - else if (maple_dev->devinfo.function & - cpu_to_be32(maple_drv->function)) - return 1; - return 0; -} - -static int maple_bus_uevent(struct device *dev, - struct kobj_uevent_env *env) -{ - return 0; -} - -static void maple_bus_release(struct device *dev) -{ -} - -static struct maple_driver maple_unsupported_device = { - .drv = { - .name = "maple_unsupported_device", - .bus = &maple_bus_type, - }, -}; -/* - * maple_bus_type - core maple bus structure - */ -struct bus_type maple_bus_type = { - .name = "maple", - .match = maple_match_bus_driver, - .uevent = maple_bus_uevent, -}; -EXPORT_SYMBOL_GPL(maple_bus_type); - -static struct device maple_bus = { - .init_name = "maple", - .release = maple_bus_release, -}; - -static int __init maple_bus_init(void) -{ - int retval, i; - struct maple_device *mdev[MAPLE_PORTS]; - - __raw_writel(0, MAPLE_ENABLE); - - retval = device_register(&maple_bus); - if (retval) - goto cleanup; - - retval = bus_register(&maple_bus_type); - if (retval) - goto cleanup_device; - - retval = driver_register(&maple_unsupported_device.drv); - if (retval) - goto cleanup_bus; - - /* allocate memory for maple bus dma */ - retval = maple_get_dma_buffer(); - if (retval) { - dev_err(&maple_bus, "failed to allocate DMA buffers\n"); - goto cleanup_basic; - } - - /* set up DMA interrupt handler */ - retval = maple_set_dma_interrupt_handler(); - if (retval) { - dev_err(&maple_bus, "bus failed to grab maple " - "DMA IRQ\n"); - goto cleanup_dma; - } - - /* set up VBLANK interrupt handler */ - retval = maple_set_vblank_interrupt_handler(); - if (retval) { - dev_err(&maple_bus, "bus failed to grab VBLANK IRQ\n"); - goto cleanup_irq; - } - - maple_queue_cache = KMEM_CACHE(maple_buffer, SLAB_HWCACHE_ALIGN); - - if (!maple_queue_cache) { - retval = -ENOMEM; - goto cleanup_bothirqs; - } - - INIT_LIST_HEAD(&maple_waitq); - INIT_LIST_HEAD(&maple_sentq); - - /* setup maple ports */ - for (i = 0; i < MAPLE_PORTS; i++) { - checked[i] = false; - empty[i] = false; - mdev[i] = maple_alloc_dev(i, 0); - if (!mdev[i]) { - while (i-- > 0) - maple_free_dev(mdev[i]); - retval = -ENOMEM; - goto cleanup_cache; - } - baseunits[i] = mdev[i]; - atomic_set(&mdev[i]->busy, 1); - maple_add_packet(mdev[i], 0, MAPLE_COMMAND_DEVINFO, 0, NULL); - subdevice_map[i] = 0; - } - - maple_pnp_time = jiffies + HZ; - /* prepare initial queue */ - maple_send(); - dev_info(&maple_bus, "bus core now registered\n"); - - return 0; - -cleanup_cache: - kmem_cache_destroy(maple_queue_cache); - -cleanup_bothirqs: - free_irq(HW_EVENT_VSYNC, 0); - -cleanup_irq: - free_irq(HW_EVENT_MAPLE_DMA, 0); - -cleanup_dma: - free_pages((unsigned long) maple_sendbuf, MAPLE_DMA_PAGES); - -cleanup_basic: - driver_unregister(&maple_unsupported_device.drv); - -cleanup_bus: - bus_unregister(&maple_bus_type); - -cleanup_device: - device_unregister(&maple_bus); - -cleanup: - printk(KERN_ERR "Maple bus registration failed\n"); - return retval; -} -/* Push init to later to ensure hardware gets detected */ -fs_initcall(maple_bus_init); diff --git a/drivers/sh/pm_runtime.c b/drivers/sh/pm_runtime.c deleted file mode 100644 index c887ecdaf19b7c..00000000000000 --- a/drivers/sh/pm_runtime.c +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Runtime PM support code - * - * Copyright (C) 2009-2010 Magnus Damm - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -static struct dev_pm_domain default_pm_domain = { - .ops = { - USE_PM_CLK_RUNTIME_OPS - USE_PLATFORM_PM_SLEEP_OPS - }, -}; - -static struct pm_clk_notifier_block platform_bus_notifier = { - .pm_domain = &default_pm_domain, - .con_ids = { NULL, }, -}; - -static int __init sh_pm_runtime_init(void) -{ - pm_clk_add_notifier(&platform_bus_type, &platform_bus_notifier); - return 0; -} -core_initcall(sh_pm_runtime_init); diff --git a/drivers/sh/superhyway/Makefile b/drivers/sh/superhyway/Makefile deleted file mode 100644 index 6dfa41f160af6b..00000000000000 --- a/drivers/sh/superhyway/Makefile +++ /dev/null @@ -1,8 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-only -# -# Makefile for the SuperHyway bus drivers. -# - -obj-$(CONFIG_SUPERHYWAY) += superhyway.o -obj-$(CONFIG_SYSFS) += superhyway-sysfs.o - diff --git a/drivers/sh/superhyway/superhyway-sysfs.c b/drivers/sh/superhyway/superhyway-sysfs.c deleted file mode 100644 index 774f31b564f8f8..00000000000000 --- a/drivers/sh/superhyway/superhyway-sysfs.c +++ /dev/null @@ -1,54 +0,0 @@ -/* - * drivers/sh/superhyway/superhyway-sysfs.c - * - * SuperHyway Bus sysfs interface - * - * Copyright (C) 2004, 2005 Paul Mundt - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - */ -#include -#include -#include -#include - -#define superhyway_ro_attr(name, fmt, field) \ -static ssize_t name##_show(struct device *dev, struct device_attribute *attr, char *buf) \ -{ \ - struct superhyway_device *s = to_superhyway_device(dev); \ - return sprintf(buf, fmt, s->field); \ -} \ -static DEVICE_ATTR_RO(name); - -/* VCR flags */ -superhyway_ro_attr(perr_flags, "0x%02x\n", vcr.perr_flags); -superhyway_ro_attr(merr_flags, "0x%02x\n", vcr.merr_flags); -superhyway_ro_attr(mod_vers, "0x%04x\n", vcr.mod_vers); -superhyway_ro_attr(mod_id, "0x%04x\n", vcr.mod_id); -superhyway_ro_attr(bot_mb, "0x%02x\n", vcr.bot_mb); -superhyway_ro_attr(top_mb, "0x%02x\n", vcr.top_mb); - -/* Misc */ -superhyway_ro_attr(resource, "0x%08lx\n", resource[0].start); - -static struct attribute *superhyway_dev_attrs[] = { - &dev_attr_perr_flags.attr, - &dev_attr_merr_flags.attr, - &dev_attr_mod_vers.attr, - &dev_attr_mod_id.attr, - &dev_attr_bot_mb.attr, - &dev_attr_top_mb.attr, - &dev_attr_resource.attr, - NULL, -}; - -static const struct attribute_group superhyway_dev_group = { - .attrs = superhyway_dev_attrs, -}; - -const struct attribute_group *superhyway_dev_groups[] = { - &superhyway_dev_group, - NULL, -}; diff --git a/drivers/sh/superhyway/superhyway.c b/drivers/sh/superhyway/superhyway.c deleted file mode 100644 index 44324abe21dada..00000000000000 --- a/drivers/sh/superhyway/superhyway.c +++ /dev/null @@ -1,234 +0,0 @@ -/* - * drivers/sh/superhyway/superhyway.c - * - * SuperHyway Bus Driver - * - * Copyright (C) 2004, 2005 Paul Mundt - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include - -static int superhyway_devices; - -static struct device superhyway_bus_device = { - .init_name = "superhyway", -}; - -static void superhyway_device_release(struct device *dev) -{ - struct superhyway_device *sdev = to_superhyway_device(dev); - - kfree(sdev->resource); - kfree(sdev); -} - -/** - * superhyway_add_device - Add a SuperHyway module - * @base: Physical address where module is mapped. - * @sdev: SuperHyway device to add, or NULL to allocate a new one. - * @bus: Bus where SuperHyway module resides. - * - * This is responsible for adding a new SuperHyway module. This sets up a new - * struct superhyway_device for the module being added if @sdev == NULL. - * - * Devices are initially added in the order that they are scanned (from the - * top-down of the memory map), and are assigned an ID based on the order that - * they are added. Any manual addition of a module will thus get the ID after - * the devices already discovered regardless of where it resides in memory. - * - * Further work can and should be done in superhyway_scan_bus(), to be sure - * that any new modules are properly discovered and subsequently registered. - */ -int superhyway_add_device(unsigned long base, struct superhyway_device *sdev, - struct superhyway_bus *bus) -{ - struct superhyway_device *dev = sdev; - - if (!dev) { - dev = kzalloc(sizeof(struct superhyway_device), GFP_KERNEL); - if (!dev) - return -ENOMEM; - - } - - dev->bus = bus; - superhyway_read_vcr(dev, base, &dev->vcr); - - if (!dev->resource) { - dev->resource = kzalloc(sizeof(struct resource), GFP_KERNEL); - if (!dev->resource) { - kfree(dev); - return -ENOMEM; - } - - dev->resource->name = dev->name; - dev->resource->start = base; - dev->resource->end = dev->resource->start + 0x01000000; - } - - dev->dev.parent = &superhyway_bus_device; - dev->dev.bus = &superhyway_bus_type; - dev->dev.release = superhyway_device_release; - dev->id.id = dev->vcr.mod_id; - - sprintf(dev->name, "SuperHyway device %04x", dev->id.id); - dev_set_name(&dev->dev, "%02x", superhyway_devices); - - superhyway_devices++; - - return device_register(&dev->dev); -} - -int superhyway_add_devices(struct superhyway_bus *bus, - struct superhyway_device **devices, - int nr_devices) -{ - int i, ret = 0; - - for (i = 0; i < nr_devices; i++) { - struct superhyway_device *dev = devices[i]; - ret |= superhyway_add_device(dev->resource[0].start, dev, bus); - } - - return ret; -} - -static int __init superhyway_init(void) -{ - struct superhyway_bus *bus; - int ret; - - ret = device_register(&superhyway_bus_device); - if (unlikely(ret)) - return ret; - - for (bus = superhyway_channels; bus->ops; bus++) - ret |= superhyway_scan_bus(bus); - - return ret; -} -postcore_initcall(superhyway_init); - -static const struct superhyway_device_id * -superhyway_match_id(const struct superhyway_device_id *ids, - struct superhyway_device *dev) -{ - while (ids->id) { - if (ids->id == dev->id.id) - return ids; - - ids++; - } - - return NULL; -} - -static int superhyway_device_probe(struct device *dev) -{ - struct superhyway_device *shyway_dev = to_superhyway_device(dev); - struct superhyway_driver *shyway_drv = to_superhyway_driver(dev->driver); - - if (shyway_drv && shyway_drv->probe) { - const struct superhyway_device_id *id; - - id = superhyway_match_id(shyway_drv->id_table, shyway_dev); - if (id) - return shyway_drv->probe(shyway_dev, id); - } - - return -ENODEV; -} - -static void superhyway_device_remove(struct device *dev) -{ - struct superhyway_device *shyway_dev = to_superhyway_device(dev); - struct superhyway_driver *shyway_drv = to_superhyway_driver(dev->driver); - - if (shyway_drv->remove) - shyway_drv->remove(shyway_dev); -} - -/** - * superhyway_register_driver - Register a new SuperHyway driver - * @drv: SuperHyway driver to register. - * - * This registers the passed in @drv. Any devices matching the id table will - * automatically be populated and handed off to the driver's specified probe - * routine. - */ -int superhyway_register_driver(struct superhyway_driver *drv) -{ - drv->drv.name = drv->name; - drv->drv.bus = &superhyway_bus_type; - - return driver_register(&drv->drv); -} - -/** - * superhyway_unregister_driver - Unregister a SuperHyway driver - * @drv: SuperHyway driver to unregister. - * - * This cleans up after superhyway_register_driver(), and should be invoked in - * the exit path of any module drivers. - */ -void superhyway_unregister_driver(struct superhyway_driver *drv) -{ - driver_unregister(&drv->drv); -} - -static int superhyway_bus_match(struct device *dev, struct device_driver *drv) -{ - struct superhyway_device *shyway_dev = to_superhyway_device(dev); - struct superhyway_driver *shyway_drv = to_superhyway_driver(drv); - const struct superhyway_device_id *ids = shyway_drv->id_table; - - if (!ids) - return -EINVAL; - if (superhyway_match_id(ids, shyway_dev)) - return 1; - - return -ENODEV; -} - -struct bus_type superhyway_bus_type = { - .name = "superhyway", - .match = superhyway_bus_match, -#ifdef CONFIG_SYSFS - .dev_groups = superhyway_dev_groups, -#endif - .probe = superhyway_device_probe, - .remove = superhyway_device_remove, -}; - -static int __init superhyway_bus_init(void) -{ - return bus_register(&superhyway_bus_type); -} - -static void __exit superhyway_bus_exit(void) -{ - device_unregister(&superhyway_bus_device); - bus_unregister(&superhyway_bus_type); -} - -core_initcall(superhyway_bus_init); -module_exit(superhyway_bus_exit); - -EXPORT_SYMBOL(superhyway_bus_type); -EXPORT_SYMBOL(superhyway_add_device); -EXPORT_SYMBOL(superhyway_add_devices); -EXPORT_SYMBOL(superhyway_register_driver); -EXPORT_SYMBOL(superhyway_unregister_driver); - -MODULE_LICENSE("GPL"); diff --git a/include/linux/sh_clk.h b/include/linux/sh_clk.h deleted file mode 100644 index 7bed5be886c657..00000000000000 --- a/include/linux/sh_clk.h +++ /dev/null @@ -1,213 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -#ifndef __SH_CLOCK_H -#define __SH_CLOCK_H - -#include -#include -#include -#include -#include -#include -#include - -struct clk; - -struct clk_mapping { - phys_addr_t phys; - void __iomem *base; - unsigned long len; - struct kref ref; -}; - -struct sh_clk_ops { -#ifdef CONFIG_SH_CLK_CPG_LEGACY - void (*init)(struct clk *clk); -#endif - int (*enable)(struct clk *clk); - void (*disable)(struct clk *clk); - unsigned long (*recalc)(struct clk *clk); - int (*set_rate)(struct clk *clk, unsigned long rate); - int (*set_parent)(struct clk *clk, struct clk *parent); - long (*round_rate)(struct clk *clk, unsigned long rate); -}; - -#define SH_CLK_DIV_MSK(div) ((1 << (div)) - 1) -#define SH_CLK_DIV4_MSK SH_CLK_DIV_MSK(4) -#define SH_CLK_DIV6_MSK SH_CLK_DIV_MSK(6) - -struct clk { - struct list_head node; - struct clk *parent; - struct clk **parent_table; /* list of parents to */ - unsigned short parent_num; /* choose between */ - unsigned char src_shift; /* source clock field in the */ - unsigned char src_width; /* configuration register */ - struct sh_clk_ops *ops; - - struct list_head children; - struct list_head sibling; /* node for children */ - - int usecount; - - unsigned long rate; - unsigned long flags; - - void __iomem *enable_reg; - void __iomem *status_reg; - unsigned int enable_bit; - void __iomem *mapped_reg; - - unsigned int div_mask; - unsigned long arch_flags; - void *priv; - struct clk_mapping *mapping; - struct cpufreq_frequency_table *freq_table; - unsigned int nr_freqs; -}; - -#define CLK_ENABLE_ON_INIT BIT(0) - -#define CLK_ENABLE_REG_32BIT BIT(1) /* default access size */ -#define CLK_ENABLE_REG_16BIT BIT(2) -#define CLK_ENABLE_REG_8BIT BIT(3) - -#define CLK_MASK_DIV_ON_DISABLE BIT(4) - -#define CLK_ENABLE_REG_MASK (CLK_ENABLE_REG_32BIT | \ - CLK_ENABLE_REG_16BIT | \ - CLK_ENABLE_REG_8BIT) - -/* drivers/sh/clk.c */ -unsigned long followparent_recalc(struct clk *); -void recalculate_root_clocks(void); -void propagate_rate(struct clk *); -int clk_reparent(struct clk *child, struct clk *parent); -int clk_register(struct clk *); -void clk_unregister(struct clk *); -void clk_enable_init_clocks(void); - -struct clk_div_mult_table { - unsigned int *divisors; - unsigned int nr_divisors; - unsigned int *multipliers; - unsigned int nr_multipliers; -}; - -struct cpufreq_frequency_table; -void clk_rate_table_build(struct clk *clk, - struct cpufreq_frequency_table *freq_table, - int nr_freqs, - struct clk_div_mult_table *src_table, - unsigned long *bitmap); - -long clk_rate_table_round(struct clk *clk, - struct cpufreq_frequency_table *freq_table, - unsigned long rate); - -int clk_rate_table_find(struct clk *clk, - struct cpufreq_frequency_table *freq_table, - unsigned long rate); - -long clk_rate_div_range_round(struct clk *clk, unsigned int div_min, - unsigned int div_max, unsigned long rate); - -long clk_rate_mult_range_round(struct clk *clk, unsigned int mult_min, - unsigned int mult_max, unsigned long rate); - -#define SH_CLK_MSTP(_parent, _enable_reg, _enable_bit, _status_reg, _flags) \ -{ \ - .parent = _parent, \ - .enable_reg = (void __iomem *)_enable_reg, \ - .enable_bit = _enable_bit, \ - .status_reg = _status_reg, \ - .flags = _flags, \ -} - -#define SH_CLK_MSTP32(_p, _r, _b, _f) \ - SH_CLK_MSTP(_p, _r, _b, 0, _f | CLK_ENABLE_REG_32BIT) - -#define SH_CLK_MSTP32_STS(_p, _r, _b, _s, _f) \ - SH_CLK_MSTP(_p, _r, _b, _s, _f | CLK_ENABLE_REG_32BIT) - -#define SH_CLK_MSTP16(_p, _r, _b, _f) \ - SH_CLK_MSTP(_p, _r, _b, 0, _f | CLK_ENABLE_REG_16BIT) - -#define SH_CLK_MSTP8(_p, _r, _b, _f) \ - SH_CLK_MSTP(_p, _r, _b, 0, _f | CLK_ENABLE_REG_8BIT) - -int sh_clk_mstp_register(struct clk *clks, int nr); - -/* - * MSTP registration never really cared about access size, despite the - * original enable/disable pairs assuming a 32-bit access. Clocks are - * responsible for defining their access sizes either directly or via the - * clock definition wrappers. - */ -static inline int __deprecated sh_clk_mstp32_register(struct clk *clks, int nr) -{ - return sh_clk_mstp_register(clks, nr); -} - -#define SH_CLK_DIV4(_parent, _reg, _shift, _div_bitmap, _flags) \ -{ \ - .parent = _parent, \ - .enable_reg = (void __iomem *)_reg, \ - .enable_bit = _shift, \ - .arch_flags = _div_bitmap, \ - .div_mask = SH_CLK_DIV4_MSK, \ - .flags = _flags, \ -} - -struct clk_div_table { - struct clk_div_mult_table *div_mult_table; - void (*kick)(struct clk *clk); -}; - -#define clk_div4_table clk_div_table - -int sh_clk_div4_register(struct clk *clks, int nr, - struct clk_div4_table *table); -int sh_clk_div4_enable_register(struct clk *clks, int nr, - struct clk_div4_table *table); -int sh_clk_div4_reparent_register(struct clk *clks, int nr, - struct clk_div4_table *table); - -#define SH_CLK_DIV6_EXT(_reg, _flags, _parents, \ - _num_parents, _src_shift, _src_width) \ -{ \ - .enable_reg = (void __iomem *)_reg, \ - .enable_bit = 0, /* unused */ \ - .flags = _flags | CLK_MASK_DIV_ON_DISABLE, \ - .div_mask = SH_CLK_DIV6_MSK, \ - .parent_table = _parents, \ - .parent_num = _num_parents, \ - .src_shift = _src_shift, \ - .src_width = _src_width, \ -} - -#define SH_CLK_DIV6(_parent, _reg, _flags) \ -{ \ - .parent = _parent, \ - .enable_reg = (void __iomem *)_reg, \ - .enable_bit = 0, /* unused */ \ - .div_mask = SH_CLK_DIV6_MSK, \ - .flags = _flags | CLK_MASK_DIV_ON_DISABLE, \ -} - -int sh_clk_div6_register(struct clk *clks, int nr); -int sh_clk_div6_reparent_register(struct clk *clks, int nr); - -#define CLKDEV_CON_ID(_id, _clk) { .con_id = _id, .clk = _clk } -#define CLKDEV_DEV_ID(_id, _clk) { .dev_id = _id, .clk = _clk } -#define CLKDEV_ICK_ID(_cid, _did, _clk) { .con_id = _cid, .dev_id = _did, .clk = _clk } - -/* .enable_reg will be updated to .mapping on sh_clk_fsidiv_register() */ -#define SH_CLK_FSIDIV(_reg, _parent) \ -{ \ - .enable_reg = (void __iomem *)_reg, \ - .parent = _parent, \ -} - -int sh_clk_fsidiv_register(struct clk *clks, int nr); - -#endif /* __SH_CLOCK_H */ diff --git a/include/linux/superhyway.h b/include/linux/superhyway.h deleted file mode 100644 index 8d3376775813d3..00000000000000 --- a/include/linux/superhyway.h +++ /dev/null @@ -1,107 +0,0 @@ -/* - * include/linux/superhyway.h - * - * SuperHyway Bus definitions - * - * Copyright (C) 2004, 2005 Paul Mundt - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - */ -#ifndef __LINUX_SUPERHYWAY_H -#define __LINUX_SUPERHYWAY_H - -#include - -/* - * SuperHyway IDs - */ -#define SUPERHYWAY_DEVICE_ID_SH5_DMAC 0x0183 - -struct superhyway_vcr_info { - u8 perr_flags; /* P-port Error flags */ - u8 merr_flags; /* Module Error flags */ - u16 mod_vers; /* Module Version */ - u16 mod_id; /* Module ID */ - u8 bot_mb; /* Bottom Memory block */ - u8 top_mb; /* Top Memory block */ -}; - -struct superhyway_ops { - int (*read_vcr)(unsigned long base, struct superhyway_vcr_info *vcr); - int (*write_vcr)(unsigned long base, struct superhyway_vcr_info vcr); -}; - -struct superhyway_bus { - struct superhyway_ops *ops; -}; - -extern struct superhyway_bus superhyway_channels[]; - -struct superhyway_device_id { - unsigned int id; - unsigned long driver_data; -}; - -struct superhyway_device; -extern struct bus_type superhyway_bus_type; - -struct superhyway_driver { - char *name; - - const struct superhyway_device_id *id_table; - struct device_driver drv; - - int (*probe)(struct superhyway_device *dev, const struct superhyway_device_id *id); - void (*remove)(struct superhyway_device *dev); -}; - -#define to_superhyway_driver(d) container_of((d), struct superhyway_driver, drv) - -struct superhyway_device { - char name[32]; - - struct device dev; - - struct superhyway_device_id id; - struct superhyway_driver *drv; - struct superhyway_bus *bus; - - int num_resources; - struct resource *resource; - struct superhyway_vcr_info vcr; -}; - -#define to_superhyway_device(d) container_of((d), struct superhyway_device, dev) - -#define superhyway_get_drvdata(d) dev_get_drvdata(&(d)->dev) -#define superhyway_set_drvdata(d,p) dev_set_drvdata(&(d)->dev, (p)) - -static inline int -superhyway_read_vcr(struct superhyway_device *dev, unsigned long base, - struct superhyway_vcr_info *vcr) -{ - return dev->bus->ops->read_vcr(base, vcr); -} - -static inline int -superhyway_write_vcr(struct superhyway_device *dev, unsigned long base, - struct superhyway_vcr_info vcr) -{ - return dev->bus->ops->write_vcr(base, vcr); -} - -extern int superhyway_scan_bus(struct superhyway_bus *); - -/* drivers/sh/superhyway/superhyway.c */ -int superhyway_register_driver(struct superhyway_driver *); -void superhyway_unregister_driver(struct superhyway_driver *); -int superhyway_add_device(unsigned long base, struct superhyway_device *, struct superhyway_bus *); -int superhyway_add_devices(struct superhyway_bus *bus, struct superhyway_device **devices, int nr_devices); - -/* drivers/sh/superhyway/superhyway-sysfs.c */ -extern const struct attribute_group *superhyway_dev_groups[]; - -#endif /* __LINUX_SUPERHYWAY_H */ - From patchwork Fri Jan 13 06:23:32 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christoph Hellwig X-Patchwork-Id: 642858 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 9A166C61DB3 for ; Fri, 13 Jan 2023 06:28:13 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S241029AbjAMG2K (ORCPT ); Fri, 13 Jan 2023 01:28:10 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:36742 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S240696AbjAMG0G (ORCPT ); Fri, 13 Jan 2023 01:26:06 -0500 Received: from bombadil.infradead.org (bombadil.infradead.org [IPv6:2607:7c80:54:3::133]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 681155A880; Thu, 12 Jan 2023 22:24:48 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=infradead.org; s=bombadil.20210309; h=Content-Transfer-Encoding: MIME-Version:References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From:Sender :Reply-To:Content-Type:Content-ID:Content-Description; bh=brkgyM1hhrmjLwT1BCvS491OM9ZvmSvWuQcY6ZdmaEQ=; b=rclg5IcyZx3hAYAW2A82gKgG/R 9h9Oe/wM1Koo+NmcZ4yMIJIFj+qyIun0yWyAuormOj2yAyWxmpqiP2tOTjglLnHiXw+LO8ETgIdA+ 5Svhx7nVkyRr8shQSGKZC980O+hinT+yIkJMia9iivbaAqpxScAjdfS1ylAfFTuFfEpPajKlizKuC x920Cmh9IN6hilV+vdW649ilBNPtNcRIhR92SLyVFpjckwWhuUlUQEzckeqR1pXS3MdV0ZyVfntjY 4ZjNun8OKq1jiBsWb6I8b5g9mXdhx5n98DESlAo/jfRw7Kht5JW4J78GkDbW2pZIH+YhQxqch531J NCRDTDXw==; Received: from [2001:4bb8:181:656b:9509:7d20:8d39:f895] (helo=localhost) by bombadil.infradead.org with esmtpsa (Exim 4.94.2 #2 (Red Hat Linux)) id 1pGDUT-000lua-TT; Fri, 13 Jan 2023 06:24:38 +0000 From: Christoph Hellwig To: Yoshinori Sato , Rich Felker , Arnd Bergmann , Greg Kroah-Hartman Cc: Laurent Pinchart , Kieran Bingham , Geert Uytterhoeven , linux-kernel@vger.kernel.org, linux-watchdog@vger.kernel.org, devicetree@vger.kernel.org, linux-arch@vger.kernel.org, dmaengine@vger.kernel.org, dri-devel@lists.freedesktop.org, linux-renesas-soc@vger.kernel.org, linux-i2c@vger.kernel.org, linux-input@vger.kernel.org, linux-media@vger.kernel.org, linux-mmc@vger.kernel.org, linux-mtd@lists.infradead.org, netdev@vger.kernel.org, linux-gpio@vger.kernel.org, linux-rtc@vger.kernel.org, linux-spi@vger.kernel.org, linux-serial@vger.kernel.org, linux-usb@vger.kernel.org, linux-fbdev@vger.kernel.org, alsa-devel@alsa-project.org, linux-sh@vger.kernel.org Subject: [PATCH 15/22] spi: remove spi-sh Date: Fri, 13 Jan 2023 07:23:32 +0100 Message-Id: <20230113062339.1909087-16-hch@lst.de> X-Mailer: git-send-email 2.39.0 In-Reply-To: <20230113062339.1909087-1-hch@lst.de> References: <20230113062339.1909087-1-hch@lst.de> MIME-Version: 1.0 X-SRS-Rewrite: SMTP reverse-path rewritten from by bombadil.infradead.org. See http://www.infradead.org/rpr.html Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org Now that arch/sh is removed this driver is dead code. Signed-off-by: Christoph Hellwig --- drivers/spi/Kconfig | 6 - drivers/spi/Makefile | 1 - drivers/spi/spi-sh.c | 474 ------------------------------------------- 3 files changed, 481 deletions(-) delete mode 100644 drivers/spi/spi-sh.c diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index 2c5226adf5e1d3..7508dcef909c78 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -882,12 +882,6 @@ config SPI_SH_MSIOF help SPI driver for SuperH and SH Mobile MSIOF blocks. -config SPI_SH - tristate "SuperH SPI controller" - depends on SUPERH || COMPILE_TEST - help - SPI driver for SuperH SPI blocks. - config SPI_SH_SCI tristate "SuperH SCI SPI controller" depends on SUPERH diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile index be9ba40ef8d03d..342a7eb5181c9b 100644 --- a/drivers/spi/Makefile +++ b/drivers/spi/Makefile @@ -116,7 +116,6 @@ obj-$(CONFIG_SPI_S3C24XX) += spi-s3c24xx-hw.o spi-s3c24xx-hw-y := spi-s3c24xx.o obj-$(CONFIG_SPI_S3C64XX) += spi-s3c64xx.o obj-$(CONFIG_SPI_SC18IS602) += spi-sc18is602.o -obj-$(CONFIG_SPI_SH) += spi-sh.o obj-$(CONFIG_SPI_SH_HSPI) += spi-sh-hspi.o obj-$(CONFIG_SPI_SH_MSIOF) += spi-sh-msiof.o obj-$(CONFIG_SPI_SH_SCI) += spi-sh-sci.o diff --git a/drivers/spi/spi-sh.c b/drivers/spi/spi-sh.c deleted file mode 100644 index 3e72fad99adfd4..00000000000000 --- a/drivers/spi/spi-sh.c +++ /dev/null @@ -1,474 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * SH SPI bus driver - * - * Copyright (C) 2011 Renesas Solutions Corp. - * - * Based on pxa2xx_spi.c: - * Copyright (C) 2005 Stephen Street / StreetFire Sound Labs - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define SPI_SH_TBR 0x00 -#define SPI_SH_RBR 0x00 -#define SPI_SH_CR1 0x08 -#define SPI_SH_CR2 0x10 -#define SPI_SH_CR3 0x18 -#define SPI_SH_CR4 0x20 -#define SPI_SH_CR5 0x28 - -/* CR1 */ -#define SPI_SH_TBE 0x80 -#define SPI_SH_TBF 0x40 -#define SPI_SH_RBE 0x20 -#define SPI_SH_RBF 0x10 -#define SPI_SH_PFONRD 0x08 -#define SPI_SH_SSDB 0x04 -#define SPI_SH_SSD 0x02 -#define SPI_SH_SSA 0x01 - -/* CR2 */ -#define SPI_SH_RSTF 0x80 -#define SPI_SH_LOOPBK 0x40 -#define SPI_SH_CPOL 0x20 -#define SPI_SH_CPHA 0x10 -#define SPI_SH_L1M0 0x08 - -/* CR3 */ -#define SPI_SH_MAX_BYTE 0xFF - -/* CR4 */ -#define SPI_SH_TBEI 0x80 -#define SPI_SH_TBFI 0x40 -#define SPI_SH_RBEI 0x20 -#define SPI_SH_RBFI 0x10 -#define SPI_SH_WPABRT 0x04 -#define SPI_SH_SSS 0x01 - -/* CR8 */ -#define SPI_SH_P1L0 0x80 -#define SPI_SH_PP1L0 0x40 -#define SPI_SH_MUXI 0x20 -#define SPI_SH_MUXIRQ 0x10 - -#define SPI_SH_FIFO_SIZE 32 -#define SPI_SH_SEND_TIMEOUT (3 * HZ) -#define SPI_SH_RECEIVE_TIMEOUT (HZ >> 3) - -#undef DEBUG - -struct spi_sh_data { - void __iomem *addr; - int irq; - struct spi_master *master; - unsigned long cr1; - wait_queue_head_t wait; - int width; -}; - -static void spi_sh_write(struct spi_sh_data *ss, unsigned long data, - unsigned long offset) -{ - if (ss->width == 8) - iowrite8(data, ss->addr + (offset >> 2)); - else if (ss->width == 32) - iowrite32(data, ss->addr + offset); -} - -static unsigned long spi_sh_read(struct spi_sh_data *ss, unsigned long offset) -{ - if (ss->width == 8) - return ioread8(ss->addr + (offset >> 2)); - else if (ss->width == 32) - return ioread32(ss->addr + offset); - else - return 0; -} - -static void spi_sh_set_bit(struct spi_sh_data *ss, unsigned long val, - unsigned long offset) -{ - unsigned long tmp; - - tmp = spi_sh_read(ss, offset); - tmp |= val; - spi_sh_write(ss, tmp, offset); -} - -static void spi_sh_clear_bit(struct spi_sh_data *ss, unsigned long val, - unsigned long offset) -{ - unsigned long tmp; - - tmp = spi_sh_read(ss, offset); - tmp &= ~val; - spi_sh_write(ss, tmp, offset); -} - -static void clear_fifo(struct spi_sh_data *ss) -{ - spi_sh_set_bit(ss, SPI_SH_RSTF, SPI_SH_CR2); - spi_sh_clear_bit(ss, SPI_SH_RSTF, SPI_SH_CR2); -} - -static int spi_sh_wait_receive_buffer(struct spi_sh_data *ss) -{ - int timeout = 100000; - - while (spi_sh_read(ss, SPI_SH_CR1) & SPI_SH_RBE) { - udelay(10); - if (timeout-- < 0) - return -ETIMEDOUT; - } - return 0; -} - -static int spi_sh_wait_write_buffer_empty(struct spi_sh_data *ss) -{ - int timeout = 100000; - - while (!(spi_sh_read(ss, SPI_SH_CR1) & SPI_SH_TBE)) { - udelay(10); - if (timeout-- < 0) - return -ETIMEDOUT; - } - return 0; -} - -static int spi_sh_send(struct spi_sh_data *ss, struct spi_message *mesg, - struct spi_transfer *t) -{ - int i, retval = 0; - int remain = t->len; - int cur_len; - unsigned char *data; - long ret; - - if (t->len) - spi_sh_set_bit(ss, SPI_SH_SSA, SPI_SH_CR1); - - data = (unsigned char *)t->tx_buf; - while (remain > 0) { - cur_len = min(SPI_SH_FIFO_SIZE, remain); - for (i = 0; i < cur_len && - !(spi_sh_read(ss, SPI_SH_CR4) & - SPI_SH_WPABRT) && - !(spi_sh_read(ss, SPI_SH_CR1) & SPI_SH_TBF); - i++) - spi_sh_write(ss, (unsigned long)data[i], SPI_SH_TBR); - - if (spi_sh_read(ss, SPI_SH_CR4) & SPI_SH_WPABRT) { - /* Abort SPI operation */ - spi_sh_set_bit(ss, SPI_SH_WPABRT, SPI_SH_CR4); - retval = -EIO; - break; - } - - cur_len = i; - - remain -= cur_len; - data += cur_len; - - if (remain > 0) { - ss->cr1 &= ~SPI_SH_TBE; - spi_sh_set_bit(ss, SPI_SH_TBE, SPI_SH_CR4); - ret = wait_event_interruptible_timeout(ss->wait, - ss->cr1 & SPI_SH_TBE, - SPI_SH_SEND_TIMEOUT); - if (ret == 0 && !(ss->cr1 & SPI_SH_TBE)) { - printk(KERN_ERR "%s: timeout\n", __func__); - return -ETIMEDOUT; - } - } - } - - if (list_is_last(&t->transfer_list, &mesg->transfers)) { - spi_sh_clear_bit(ss, SPI_SH_SSD | SPI_SH_SSDB, SPI_SH_CR1); - spi_sh_set_bit(ss, SPI_SH_SSA, SPI_SH_CR1); - - ss->cr1 &= ~SPI_SH_TBE; - spi_sh_set_bit(ss, SPI_SH_TBE, SPI_SH_CR4); - ret = wait_event_interruptible_timeout(ss->wait, - ss->cr1 & SPI_SH_TBE, - SPI_SH_SEND_TIMEOUT); - if (ret == 0 && (ss->cr1 & SPI_SH_TBE)) { - printk(KERN_ERR "%s: timeout\n", __func__); - return -ETIMEDOUT; - } - } - - return retval; -} - -static int spi_sh_receive(struct spi_sh_data *ss, struct spi_message *mesg, - struct spi_transfer *t) -{ - int i; - int remain = t->len; - int cur_len; - unsigned char *data; - long ret; - - if (t->len > SPI_SH_MAX_BYTE) - spi_sh_write(ss, SPI_SH_MAX_BYTE, SPI_SH_CR3); - else - spi_sh_write(ss, t->len, SPI_SH_CR3); - - spi_sh_clear_bit(ss, SPI_SH_SSD | SPI_SH_SSDB, SPI_SH_CR1); - spi_sh_set_bit(ss, SPI_SH_SSA, SPI_SH_CR1); - - spi_sh_wait_write_buffer_empty(ss); - - data = (unsigned char *)t->rx_buf; - while (remain > 0) { - if (remain >= SPI_SH_FIFO_SIZE) { - ss->cr1 &= ~SPI_SH_RBF; - spi_sh_set_bit(ss, SPI_SH_RBF, SPI_SH_CR4); - ret = wait_event_interruptible_timeout(ss->wait, - ss->cr1 & SPI_SH_RBF, - SPI_SH_RECEIVE_TIMEOUT); - if (ret == 0 && - spi_sh_read(ss, SPI_SH_CR1) & SPI_SH_RBE) { - printk(KERN_ERR "%s: timeout\n", __func__); - return -ETIMEDOUT; - } - } - - cur_len = min(SPI_SH_FIFO_SIZE, remain); - for (i = 0; i < cur_len; i++) { - if (spi_sh_wait_receive_buffer(ss)) - break; - data[i] = (unsigned char)spi_sh_read(ss, SPI_SH_RBR); - } - - remain -= cur_len; - data += cur_len; - } - - /* deassert CS when SPI is receiving. */ - if (t->len > SPI_SH_MAX_BYTE) { - clear_fifo(ss); - spi_sh_write(ss, 1, SPI_SH_CR3); - } else { - spi_sh_write(ss, 0, SPI_SH_CR3); - } - - return 0; -} - -static int spi_sh_transfer_one_message(struct spi_controller *ctlr, - struct spi_message *mesg) -{ - struct spi_sh_data *ss = spi_controller_get_devdata(ctlr); - struct spi_transfer *t; - int ret; - - pr_debug("%s: enter\n", __func__); - - spi_sh_clear_bit(ss, SPI_SH_SSA, SPI_SH_CR1); - - list_for_each_entry(t, &mesg->transfers, transfer_list) { - pr_debug("tx_buf = %p, rx_buf = %p\n", - t->tx_buf, t->rx_buf); - pr_debug("len = %d, delay.value = %d\n", - t->len, t->delay.value); - - if (t->tx_buf) { - ret = spi_sh_send(ss, mesg, t); - if (ret < 0) - goto error; - } - if (t->rx_buf) { - ret = spi_sh_receive(ss, mesg, t); - if (ret < 0) - goto error; - } - mesg->actual_length += t->len; - } - - mesg->status = 0; - spi_finalize_current_message(ctlr); - - clear_fifo(ss); - spi_sh_set_bit(ss, SPI_SH_SSD, SPI_SH_CR1); - udelay(100); - - spi_sh_clear_bit(ss, SPI_SH_SSA | SPI_SH_SSDB | SPI_SH_SSD, - SPI_SH_CR1); - - clear_fifo(ss); - - return 0; - - error: - mesg->status = ret; - spi_finalize_current_message(ctlr); - if (mesg->complete) - mesg->complete(mesg->context); - - spi_sh_clear_bit(ss, SPI_SH_SSA | SPI_SH_SSDB | SPI_SH_SSD, - SPI_SH_CR1); - clear_fifo(ss); - - return ret; -} - -static int spi_sh_setup(struct spi_device *spi) -{ - struct spi_sh_data *ss = spi_master_get_devdata(spi->master); - - pr_debug("%s: enter\n", __func__); - - spi_sh_write(ss, 0xfe, SPI_SH_CR1); /* SPI sycle stop */ - spi_sh_write(ss, 0x00, SPI_SH_CR1); /* CR1 init */ - spi_sh_write(ss, 0x00, SPI_SH_CR3); /* CR3 init */ - - clear_fifo(ss); - - /* 1/8 clock */ - spi_sh_write(ss, spi_sh_read(ss, SPI_SH_CR2) | 0x07, SPI_SH_CR2); - udelay(10); - - return 0; -} - -static void spi_sh_cleanup(struct spi_device *spi) -{ - struct spi_sh_data *ss = spi_master_get_devdata(spi->master); - - pr_debug("%s: enter\n", __func__); - - spi_sh_clear_bit(ss, SPI_SH_SSA | SPI_SH_SSDB | SPI_SH_SSD, - SPI_SH_CR1); -} - -static irqreturn_t spi_sh_irq(int irq, void *_ss) -{ - struct spi_sh_data *ss = (struct spi_sh_data *)_ss; - unsigned long cr1; - - cr1 = spi_sh_read(ss, SPI_SH_CR1); - if (cr1 & SPI_SH_TBE) - ss->cr1 |= SPI_SH_TBE; - if (cr1 & SPI_SH_TBF) - ss->cr1 |= SPI_SH_TBF; - if (cr1 & SPI_SH_RBE) - ss->cr1 |= SPI_SH_RBE; - if (cr1 & SPI_SH_RBF) - ss->cr1 |= SPI_SH_RBF; - - if (ss->cr1) { - spi_sh_clear_bit(ss, ss->cr1, SPI_SH_CR4); - wake_up(&ss->wait); - } - - return IRQ_HANDLED; -} - -static int spi_sh_remove(struct platform_device *pdev) -{ - struct spi_sh_data *ss = platform_get_drvdata(pdev); - - spi_unregister_master(ss->master); - free_irq(ss->irq, ss); - - return 0; -} - -static int spi_sh_probe(struct platform_device *pdev) -{ - struct resource *res; - struct spi_master *master; - struct spi_sh_data *ss; - int ret, irq; - - /* get base addr */ - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (unlikely(res == NULL)) { - dev_err(&pdev->dev, "invalid resource\n"); - return -EINVAL; - } - - irq = platform_get_irq(pdev, 0); - if (irq < 0) - return irq; - - master = devm_spi_alloc_master(&pdev->dev, sizeof(struct spi_sh_data)); - if (master == NULL) { - dev_err(&pdev->dev, "spi_alloc_master error.\n"); - return -ENOMEM; - } - - ss = spi_master_get_devdata(master); - platform_set_drvdata(pdev, ss); - - switch (res->flags & IORESOURCE_MEM_TYPE_MASK) { - case IORESOURCE_MEM_8BIT: - ss->width = 8; - break; - case IORESOURCE_MEM_32BIT: - ss->width = 32; - break; - default: - dev_err(&pdev->dev, "No support width\n"); - return -ENODEV; - } - ss->irq = irq; - ss->master = master; - ss->addr = devm_ioremap(&pdev->dev, res->start, resource_size(res)); - if (ss->addr == NULL) { - dev_err(&pdev->dev, "ioremap error.\n"); - return -ENOMEM; - } - init_waitqueue_head(&ss->wait); - - ret = request_irq(irq, spi_sh_irq, 0, "spi_sh", ss); - if (ret < 0) { - dev_err(&pdev->dev, "request_irq error\n"); - return ret; - } - - master->num_chipselect = 2; - master->bus_num = pdev->id; - master->setup = spi_sh_setup; - master->transfer_one_message = spi_sh_transfer_one_message; - master->cleanup = spi_sh_cleanup; - - ret = spi_register_master(master); - if (ret < 0) { - printk(KERN_ERR "spi_register_master error.\n"); - goto error3; - } - - return 0; - - error3: - free_irq(irq, ss); - return ret; -} - -static struct platform_driver spi_sh_driver = { - .probe = spi_sh_probe, - .remove = spi_sh_remove, - .driver = { - .name = "sh_spi", - }, -}; -module_platform_driver(spi_sh_driver); - -MODULE_DESCRIPTION("SH SPI bus driver"); -MODULE_LICENSE("GPL v2"); -MODULE_AUTHOR("Yoshihiro Shimoda"); -MODULE_ALIAS("platform:sh_spi"); From patchwork Fri Jan 13 06:23:34 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christoph Hellwig X-Patchwork-Id: 642854 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 53320C677F1 for ; Fri, 13 Jan 2023 06:31:17 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232594AbjAMGbP (ORCPT ); Fri, 13 Jan 2023 01:31:15 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:37566 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S240753AbjAMG0t (ORCPT ); Fri, 13 Jan 2023 01:26:49 -0500 Received: from bombadil.infradead.org (bombadil.infradead.org [IPv6:2607:7c80:54:3::133]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 873DE5BA14; Thu, 12 Jan 2023 22:24:57 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=infradead.org; s=bombadil.20210309; h=Content-Transfer-Encoding: MIME-Version:References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From:Sender :Reply-To:Content-Type:Content-ID:Content-Description; bh=iukbm4IkjfomIK3EfPQb3pM2uZtgleJjPX7CiCdGPsw=; b=bctQ26YIIgDNETWqWEH1faeoiC 5ktgEfTapXGrurmR9U4e7rnZhY6Cwur/HNcTFDEguI7nrrjhQMk5LJZRnXQk/Lh/SgAsj5oUR1cNC 6SWrceAqwQKLhXM4b9+5hQvSpMqgJj6Fi1i/TaketNXyVfW/AwoYVQnx70z7dzq4fJub9GsHbuyZ5 HDmhDiNuu8m8OdZDuEJyIrydgrmSdNheR0U9+6Rotsg72jUQftqVDSCn6tM1GTULxOLQT60TelhnY qeYO2LcPFeCb7ZL/Bxwy4AWEhdIRBjlajWtTjxyUMXW5KzAfXsUm2V07QOaprHacrHX0gFnJIBipd ZAhGSquQ==; Received: from [2001:4bb8:181:656b:9509:7d20:8d39:f895] (helo=localhost) by bombadil.infradead.org with esmtpsa (Exim 4.94.2 #2 (Red Hat Linux)) id 1pGDUZ-000lye-Sk; Fri, 13 Jan 2023 06:24:44 +0000 From: Christoph Hellwig To: Yoshinori Sato , Rich Felker , Arnd Bergmann , Greg Kroah-Hartman Cc: Laurent Pinchart , Kieran Bingham , Geert Uytterhoeven , linux-kernel@vger.kernel.org, linux-watchdog@vger.kernel.org, devicetree@vger.kernel.org, linux-arch@vger.kernel.org, dmaengine@vger.kernel.org, dri-devel@lists.freedesktop.org, linux-renesas-soc@vger.kernel.org, linux-i2c@vger.kernel.org, linux-input@vger.kernel.org, linux-media@vger.kernel.org, linux-mmc@vger.kernel.org, linux-mtd@lists.infradead.org, netdev@vger.kernel.org, linux-gpio@vger.kernel.org, linux-rtc@vger.kernel.org, linux-spi@vger.kernel.org, linux-serial@vger.kernel.org, linux-usb@vger.kernel.org, linux-fbdev@vger.kernel.org, alsa-devel@alsa-project.org, linux-sh@vger.kernel.org Subject: [PATCH 17/22] spi: remove spi-jcore Date: Fri, 13 Jan 2023 07:23:34 +0100 Message-Id: <20230113062339.1909087-18-hch@lst.de> X-Mailer: git-send-email 2.39.0 In-Reply-To: <20230113062339.1909087-1-hch@lst.de> References: <20230113062339.1909087-1-hch@lst.de> MIME-Version: 1.0 X-SRS-Rewrite: SMTP reverse-path rewritten from by bombadil.infradead.org. See http://www.infradead.org/rpr.html Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org Now that arch/sh is removed this driver is dead code. Signed-off-by: Christoph Hellwig --- drivers/spi/Kconfig | 7 -- drivers/spi/Makefile | 1 - drivers/spi/spi-jcore.c | 235 ---------------------------------------- 3 files changed, 243 deletions(-) delete mode 100644 drivers/spi/spi-jcore.c diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index 76f3bc6f8c81fc..17c75f5c19be75 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -483,13 +483,6 @@ config SPI_INTEL_PLATFORM To compile this driver as a module, choose M here: the module will be called spi-intel-platform. -config SPI_JCORE - tristate "J-Core SPI Master" - depends on OF && (SUPERH || COMPILE_TEST) - help - This enables support for the SPI master controller in the J-Core - synthesizable, open source SoC. - config SPI_LM70_LLP tristate "Parallel port adapter for LM70 eval board (DEVELOPMENT)" depends on PARPORT diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile index 27d877440c6539..2d03fcefc11ea2 100644 --- a/drivers/spi/Makefile +++ b/drivers/spi/Makefile @@ -67,7 +67,6 @@ obj-$(CONFIG_SPI_INTEL) += spi-intel.o obj-$(CONFIG_SPI_INTEL_PCI) += spi-intel-pci.o obj-$(CONFIG_SPI_INTEL_PLATFORM) += spi-intel-platform.o obj-$(CONFIG_SPI_LANTIQ_SSC) += spi-lantiq-ssc.o -obj-$(CONFIG_SPI_JCORE) += spi-jcore.o obj-$(CONFIG_SPI_LM70_LLP) += spi-lm70llp.o obj-$(CONFIG_SPI_LP8841_RTC) += spi-lp8841-rtc.o obj-$(CONFIG_SPI_MESON_SPICC) += spi-meson-spicc.o diff --git a/drivers/spi/spi-jcore.c b/drivers/spi/spi-jcore.c deleted file mode 100644 index 74c8319c29f170..00000000000000 --- a/drivers/spi/spi-jcore.c +++ /dev/null @@ -1,235 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * J-Core SPI controller driver - * - * Copyright (C) 2012-2016 Smart Energy Instruments, Inc. - * - * Current version by Rich Felker - * Based loosely on initial version by Oleksandr G Zhadan - * - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define DRV_NAME "jcore_spi" - -#define CTRL_REG 0x0 -#define DATA_REG 0x4 - -#define JCORE_SPI_CTRL_XMIT 0x02 -#define JCORE_SPI_STAT_BUSY 0x02 -#define JCORE_SPI_CTRL_LOOP 0x08 -#define JCORE_SPI_CTRL_CS_BITS 0x15 - -#define JCORE_SPI_WAIT_RDY_MAX_LOOP 2000000 - -struct jcore_spi { - struct spi_master *master; - void __iomem *base; - unsigned int cs_reg; - unsigned int speed_reg; - unsigned int speed_hz; - unsigned int clock_freq; -}; - -static int jcore_spi_wait(void __iomem *ctrl_reg) -{ - unsigned timeout = JCORE_SPI_WAIT_RDY_MAX_LOOP; - - do { - if (!(readl(ctrl_reg) & JCORE_SPI_STAT_BUSY)) - return 0; - cpu_relax(); - } while (--timeout); - - return -EBUSY; -} - -static void jcore_spi_program(struct jcore_spi *hw) -{ - void __iomem *ctrl_reg = hw->base + CTRL_REG; - - if (jcore_spi_wait(ctrl_reg)) - dev_err(hw->master->dev.parent, - "timeout waiting to program ctrl reg.\n"); - - writel(hw->cs_reg | hw->speed_reg, ctrl_reg); -} - -static void jcore_spi_chipsel(struct spi_device *spi, bool value) -{ - struct jcore_spi *hw = spi_master_get_devdata(spi->master); - u32 csbit = 1U << (2 * spi->chip_select); - - dev_dbg(hw->master->dev.parent, "chipselect %d\n", spi->chip_select); - - if (value) - hw->cs_reg |= csbit; - else - hw->cs_reg &= ~csbit; - - jcore_spi_program(hw); -} - -static void jcore_spi_baudrate(struct jcore_spi *hw, int speed) -{ - if (speed == hw->speed_hz) - return; - hw->speed_hz = speed; - if (speed >= hw->clock_freq / 2) - hw->speed_reg = 0; - else - hw->speed_reg = ((hw->clock_freq / 2 / speed) - 1) << 27; - jcore_spi_program(hw); - dev_dbg(hw->master->dev.parent, "speed=%d reg=0x%x\n", - speed, hw->speed_reg); -} - -static int jcore_spi_txrx(struct spi_master *master, struct spi_device *spi, - struct spi_transfer *t) -{ - struct jcore_spi *hw = spi_master_get_devdata(master); - - void __iomem *ctrl_reg = hw->base + CTRL_REG; - void __iomem *data_reg = hw->base + DATA_REG; - u32 xmit; - - /* data buffers */ - const unsigned char *tx; - unsigned char *rx; - unsigned int len; - unsigned int count; - - jcore_spi_baudrate(hw, t->speed_hz); - - xmit = hw->cs_reg | hw->speed_reg | JCORE_SPI_CTRL_XMIT; - tx = t->tx_buf; - rx = t->rx_buf; - len = t->len; - - for (count = 0; count < len; count++) { - if (jcore_spi_wait(ctrl_reg)) - break; - - writel(tx ? *tx++ : 0, data_reg); - writel(xmit, ctrl_reg); - - if (jcore_spi_wait(ctrl_reg)) - break; - - if (rx) - *rx++ = readl(data_reg); - } - - spi_finalize_current_transfer(master); - - if (count < len) - return -EREMOTEIO; - - return 0; -} - -static int jcore_spi_probe(struct platform_device *pdev) -{ - struct device_node *node = pdev->dev.of_node; - struct jcore_spi *hw; - struct spi_master *master; - struct resource *res; - u32 clock_freq; - struct clk *clk; - int err = -ENODEV; - - master = spi_alloc_master(&pdev->dev, sizeof(struct jcore_spi)); - if (!master) - return err; - - /* Setup the master state. */ - master->num_chipselect = 3; - master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH; - master->transfer_one = jcore_spi_txrx; - master->set_cs = jcore_spi_chipsel; - master->dev.of_node = node; - master->bus_num = pdev->id; - - hw = spi_master_get_devdata(master); - hw->master = master; - platform_set_drvdata(pdev, hw); - - /* Find and map our resources */ - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) - goto exit_busy; - if (!devm_request_mem_region(&pdev->dev, res->start, - resource_size(res), pdev->name)) - goto exit_busy; - hw->base = devm_ioremap(&pdev->dev, res->start, - resource_size(res)); - if (!hw->base) - goto exit_busy; - - /* - * The SPI clock rate controlled via a configurable clock divider - * which is applied to the reference clock. A 50 MHz reference is - * most suitable for obtaining standard SPI clock rates, but some - * designs may have a different reference clock, and the DT must - * make the driver aware so that it can properly program the - * requested rate. If the clock is omitted, 50 MHz is assumed. - */ - clock_freq = 50000000; - clk = devm_clk_get(&pdev->dev, "ref_clk"); - if (!IS_ERR(clk)) { - if (clk_prepare_enable(clk) == 0) { - clock_freq = clk_get_rate(clk); - clk_disable_unprepare(clk); - } else - dev_warn(&pdev->dev, "could not enable ref_clk\n"); - } - hw->clock_freq = clock_freq; - - /* Initialize all CS bits to high. */ - hw->cs_reg = JCORE_SPI_CTRL_CS_BITS; - jcore_spi_baudrate(hw, 400000); - - /* Register our spi controller */ - err = devm_spi_register_master(&pdev->dev, master); - if (err) - goto exit; - - return 0; - -exit_busy: - err = -EBUSY; -exit: - spi_master_put(master); - return err; -} - -static const struct of_device_id jcore_spi_of_match[] = { - { .compatible = "jcore,spi2" }, - {}, -}; -MODULE_DEVICE_TABLE(of, jcore_spi_of_match); - -static struct platform_driver jcore_spi_driver = { - .probe = jcore_spi_probe, - .driver = { - .name = DRV_NAME, - .of_match_table = jcore_spi_of_match, - }, -}; - -module_platform_driver(jcore_spi_driver); - -MODULE_DESCRIPTION("J-Core SPI driver"); -MODULE_AUTHOR("Rich Felker "); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:" DRV_NAME); From patchwork Fri Jan 13 06:23:35 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christoph Hellwig X-Patchwork-Id: 642856 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 8D93FC678DC for ; Fri, 13 Jan 2023 06:31:09 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S241441AbjAMGbH (ORCPT ); Fri, 13 Jan 2023 01:31:07 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:33422 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S240759AbjAMG0u (ORCPT ); Fri, 13 Jan 2023 01:26:50 -0500 Received: from bombadil.infradead.org (bombadil.infradead.org [IPv6:2607:7c80:54:3::133]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id EF2B55BA16; Thu, 12 Jan 2023 22:24:58 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=infradead.org; s=bombadil.20210309; h=Content-Transfer-Encoding: MIME-Version:References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From:Sender :Reply-To:Content-Type:Content-ID:Content-Description; bh=UA3Wx2g8+e+Fb1QaXEWK5OP24rFFtFCQfYxWGC/7x1s=; b=NgPhSrF34f2zcVzS0tgAL6SgbE zRtNJPHFDmvbOdI3GA8GgIGbclB1ExF6UYx3/DOow16PdNqNFgArlB6/7DeVG8QXv9klWNTE8z76X RxDxcxbzx1a5/02Maj5eBCzCASpahQtLWA2keIRijYtli8Z/MLfSY9hHS0VU+LPEPmMxQpGIWA7ec 3SfxmuGWVMyYB1NxTK6cbQ94YpmydUsc9sm9uGHn71o4BEIUZobj8AWNqdv6668P1fZZLhJM/SiY9 6mtAfE5wns/6VQmwdJIZFuUB6Mw5tHauSYYU3JYD4h2ywkt/BsuHr9keJXWSSnIiIpSqtpoa6ATWh Wd4bfZDA==; Received: from [2001:4bb8:181:656b:9509:7d20:8d39:f895] (helo=localhost) by bombadil.infradead.org with esmtpsa (Exim 4.94.2 #2 (Red Hat Linux)) id 1pGDUc-000m1U-Nf; Fri, 13 Jan 2023 06:24:47 +0000 From: Christoph Hellwig To: Yoshinori Sato , Rich Felker , Arnd Bergmann , Greg Kroah-Hartman Cc: Laurent Pinchart , Kieran Bingham , Geert Uytterhoeven , linux-kernel@vger.kernel.org, linux-watchdog@vger.kernel.org, devicetree@vger.kernel.org, linux-arch@vger.kernel.org, dmaengine@vger.kernel.org, dri-devel@lists.freedesktop.org, linux-renesas-soc@vger.kernel.org, linux-i2c@vger.kernel.org, linux-input@vger.kernel.org, linux-media@vger.kernel.org, linux-mmc@vger.kernel.org, linux-mtd@lists.infradead.org, netdev@vger.kernel.org, linux-gpio@vger.kernel.org, linux-rtc@vger.kernel.org, linux-spi@vger.kernel.org, linux-serial@vger.kernel.org, linux-usb@vger.kernel.org, linux-fbdev@vger.kernel.org, alsa-devel@alsa-project.org, linux-sh@vger.kernel.org Subject: [PATCH 18/22] usb: remove ehci-sh Date: Fri, 13 Jan 2023 07:23:35 +0100 Message-Id: <20230113062339.1909087-19-hch@lst.de> X-Mailer: git-send-email 2.39.0 In-Reply-To: <20230113062339.1909087-1-hch@lst.de> References: <20230113062339.1909087-1-hch@lst.de> MIME-Version: 1.0 X-SRS-Rewrite: SMTP reverse-path rewritten from by bombadil.infradead.org. See http://www.infradead.org/rpr.html Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org Now that arch/sh is removed this driver is dead code. Signed-off-by: Christoph Hellwig --- drivers/usb/host/Kconfig | 7 -- drivers/usb/host/ehci-hcd.c | 7 -- drivers/usb/host/ehci-sh.c | 182 ------------------------------------ 3 files changed, 196 deletions(-) delete mode 100644 drivers/usb/host/ehci-sh.c diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index ca5f657c092cf4..ddd8b798626caf 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig @@ -279,13 +279,6 @@ config USB_EHCI_HCD_PPC_OF Enables support for the USB controller present on the PowerPC OpenFirmware platform bus. -config USB_EHCI_SH - bool "EHCI support for SuperH USB controller" - depends on SUPERH || COMPILE_TEST - help - Enables support for the on-chip EHCI controller on the SuperH. - If you use the PCI EHCI controller, this option is not necessary. - config USB_EHCI_EXYNOS tristate "EHCI support for Samsung S5P/Exynos SoC Series" depends on ARCH_S5PV210 || ARCH_EXYNOS || COMPILE_TEST diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index a1930db0da1c3c..e6dfef3492aabe 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -1309,10 +1309,6 @@ MODULE_DESCRIPTION(DRIVER_DESC); MODULE_AUTHOR (DRIVER_AUTHOR); MODULE_LICENSE ("GPL"); -#ifdef CONFIG_USB_EHCI_SH -#include "ehci-sh.c" -#endif - #ifdef CONFIG_PPC_PS3 #include "ehci-ps3.c" #endif @@ -1330,9 +1326,6 @@ MODULE_LICENSE ("GPL"); #endif static struct platform_driver * const platform_drivers[] = { -#ifdef CONFIG_USB_EHCI_SH - &ehci_hcd_sh_driver, -#endif #ifdef CONFIG_USB_EHCI_HCD_PPC_OF &ehci_hcd_ppc_of_driver, #endif diff --git a/drivers/usb/host/ehci-sh.c b/drivers/usb/host/ehci-sh.c deleted file mode 100644 index c25c51d26f2603..00000000000000 --- a/drivers/usb/host/ehci-sh.c +++ /dev/null @@ -1,182 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * SuperH EHCI host controller driver - * - * Copyright (C) 2010 Paul Mundt - * - * Based on ohci-sh.c and ehci-atmel.c. - */ -#include -#include - -struct ehci_sh_priv { - struct clk *iclk, *fclk; - struct usb_hcd *hcd; -}; - -static int ehci_sh_reset(struct usb_hcd *hcd) -{ - struct ehci_hcd *ehci = hcd_to_ehci(hcd); - - ehci->caps = hcd->regs; - - return ehci_setup(hcd); -} - -static const struct hc_driver ehci_sh_hc_driver = { - .description = hcd_name, - .product_desc = "SuperH EHCI", - .hcd_priv_size = sizeof(struct ehci_hcd), - - /* - * generic hardware linkage - */ - .irq = ehci_irq, - .flags = HCD_USB2 | HCD_DMA | HCD_MEMORY | HCD_BH, - - /* - * basic lifecycle operations - */ - .reset = ehci_sh_reset, - .start = ehci_run, - .stop = ehci_stop, - .shutdown = ehci_shutdown, - - /* - * managing i/o requests and associated device resources - */ - .urb_enqueue = ehci_urb_enqueue, - .urb_dequeue = ehci_urb_dequeue, - .endpoint_disable = ehci_endpoint_disable, - .endpoint_reset = ehci_endpoint_reset, - - /* - * scheduling support - */ - .get_frame_number = ehci_get_frame, - - /* - * root hub support - */ - .hub_status_data = ehci_hub_status_data, - .hub_control = ehci_hub_control, - -#ifdef CONFIG_PM - .bus_suspend = ehci_bus_suspend, - .bus_resume = ehci_bus_resume, -#endif - - .relinquish_port = ehci_relinquish_port, - .port_handed_over = ehci_port_handed_over, - .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete, -}; - -static int ehci_hcd_sh_probe(struct platform_device *pdev) -{ - struct resource *res; - struct ehci_sh_priv *priv; - struct usb_hcd *hcd; - int irq, ret; - - if (usb_disabled()) - return -ENODEV; - - irq = platform_get_irq(pdev, 0); - if (irq <= 0) { - ret = -ENODEV; - goto fail_create_hcd; - } - - /* initialize hcd */ - hcd = usb_create_hcd(&ehci_sh_hc_driver, &pdev->dev, - dev_name(&pdev->dev)); - if (!hcd) { - ret = -ENOMEM; - goto fail_create_hcd; - } - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - hcd->regs = devm_ioremap_resource(&pdev->dev, res); - if (IS_ERR(hcd->regs)) { - ret = PTR_ERR(hcd->regs); - goto fail_request_resource; - } - hcd->rsrc_start = res->start; - hcd->rsrc_len = resource_size(res); - - priv = devm_kzalloc(&pdev->dev, sizeof(struct ehci_sh_priv), - GFP_KERNEL); - if (!priv) { - ret = -ENOMEM; - goto fail_request_resource; - } - - /* These are optional, we don't care if they fail */ - priv->fclk = devm_clk_get(&pdev->dev, "usb_fck"); - if (IS_ERR(priv->fclk)) - priv->fclk = NULL; - - priv->iclk = devm_clk_get(&pdev->dev, "usb_ick"); - if (IS_ERR(priv->iclk)) - priv->iclk = NULL; - - clk_enable(priv->fclk); - clk_enable(priv->iclk); - - ret = usb_add_hcd(hcd, irq, IRQF_SHARED); - if (ret != 0) { - dev_err(&pdev->dev, "Failed to add hcd"); - goto fail_add_hcd; - } - device_wakeup_enable(hcd->self.controller); - - priv->hcd = hcd; - platform_set_drvdata(pdev, priv); - - return ret; - -fail_add_hcd: - clk_disable(priv->iclk); - clk_disable(priv->fclk); - -fail_request_resource: - usb_put_hcd(hcd); -fail_create_hcd: - dev_err(&pdev->dev, "init %s fail, %d\n", dev_name(&pdev->dev), ret); - - return ret; -} - -static int ehci_hcd_sh_remove(struct platform_device *pdev) -{ - struct ehci_sh_priv *priv = platform_get_drvdata(pdev); - struct usb_hcd *hcd = priv->hcd; - - usb_remove_hcd(hcd); - usb_put_hcd(hcd); - - clk_disable(priv->fclk); - clk_disable(priv->iclk); - - return 0; -} - -static void ehci_hcd_sh_shutdown(struct platform_device *pdev) -{ - struct ehci_sh_priv *priv = platform_get_drvdata(pdev); - struct usb_hcd *hcd = priv->hcd; - - if (hcd->driver->shutdown) - hcd->driver->shutdown(hcd); -} - -static struct platform_driver ehci_hcd_sh_driver = { - .probe = ehci_hcd_sh_probe, - .remove = ehci_hcd_sh_remove, - .shutdown = ehci_hcd_sh_shutdown, - .driver = { - .name = "sh_ehci", - }, -}; - -MODULE_ALIAS("platform:sh_ehci"); From patchwork Fri Jan 13 06:23:37 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christoph Hellwig X-Patchwork-Id: 642855 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 5F604C61DB3 for ; Fri, 13 Jan 2023 06:31:10 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230473AbjAMGbJ (ORCPT ); Fri, 13 Jan 2023 01:31:09 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:33438 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S235576AbjAMG1H (ORCPT ); Fri, 13 Jan 2023 01:27:07 -0500 Received: from bombadil.infradead.org (bombadil.infradead.org [IPv6:2607:7c80:54:3::133]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 505765C1CD; Thu, 12 Jan 2023 22:25:08 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=infradead.org; s=bombadil.20210309; h=Content-Transfer-Encoding: MIME-Version:References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From:Sender :Reply-To:Content-Type:Content-ID:Content-Description; bh=mVSad5lHjsb+kxcSGYOjz7Q3t7OZ/7w3LWvLI7wl90c=; b=dTK4NKZNZ24B+Iy3vetLl8In0m 6QyXKjhgkJrMmLcUyhOZKbm0vIupFnylr7pYV8S2hu8IL5FEJ97IN1LaPho1YjqLe7sI4/ONQJffd HrN4knY96XfBH5Dg16XcB4D80tb+duR4+tun9eS3VUi93MmJDYYqXUhNRhigBMvcX6O86ZVpgYnP0 Oxo0qqd0c7Q9G2IGb9v1zvuuBflZwymgNPjOxWZjze2G/7PRQRiTyI0cvMRK8B8AtZNO1IocwGSOj LywcuT2MFfxcH/2VNQ6voqoVr4Z3t4S8OtiyGNcDIfWd6cbKEA49ubHxa8fQ7cQSeujuP6MMQBLYI oC2zjRYw==; Received: from [2001:4bb8:181:656b:9509:7d20:8d39:f895] (helo=localhost) by bombadil.infradead.org with esmtpsa (Exim 4.94.2 #2 (Red Hat Linux)) id 1pGDUi-000m58-BO; Fri, 13 Jan 2023 06:24:53 +0000 From: Christoph Hellwig To: Yoshinori Sato , Rich Felker , Arnd Bergmann , Greg Kroah-Hartman Cc: Laurent Pinchart , Kieran Bingham , Geert Uytterhoeven , linux-kernel@vger.kernel.org, linux-watchdog@vger.kernel.org, devicetree@vger.kernel.org, linux-arch@vger.kernel.org, dmaengine@vger.kernel.org, dri-devel@lists.freedesktop.org, linux-renesas-soc@vger.kernel.org, linux-i2c@vger.kernel.org, linux-input@vger.kernel.org, linux-media@vger.kernel.org, linux-mmc@vger.kernel.org, linux-mtd@lists.infradead.org, netdev@vger.kernel.org, linux-gpio@vger.kernel.org, linux-rtc@vger.kernel.org, linux-spi@vger.kernel.org, linux-serial@vger.kernel.org, linux-usb@vger.kernel.org, linux-fbdev@vger.kernel.org, alsa-devel@alsa-project.org, linux-sh@vger.kernel.org Subject: [PATCH 20/22] media: remove sh_vou Date: Fri, 13 Jan 2023 07:23:37 +0100 Message-Id: <20230113062339.1909087-21-hch@lst.de> X-Mailer: git-send-email 2.39.0 In-Reply-To: <20230113062339.1909087-1-hch@lst.de> References: <20230113062339.1909087-1-hch@lst.de> MIME-Version: 1.0 X-SRS-Rewrite: SMTP reverse-path rewritten from by bombadil.infradead.org. See http://www.infradead.org/rpr.html Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org Now that arch/sh is removed this driver is dead code. Signed-off-by: Christoph Hellwig --- drivers/media/platform/renesas/Kconfig | 9 - drivers/media/platform/renesas/Makefile | 1 - drivers/media/platform/renesas/sh_vou.c | 1375 ----------------------- 3 files changed, 1385 deletions(-) delete mode 100644 drivers/media/platform/renesas/sh_vou.c diff --git a/drivers/media/platform/renesas/Kconfig b/drivers/media/platform/renesas/Kconfig index 0231672a7e1c32..935b24b864380e 100644 --- a/drivers/media/platform/renesas/Kconfig +++ b/drivers/media/platform/renesas/Kconfig @@ -31,15 +31,6 @@ config VIDEO_RCAR_ISP To compile this driver as a module, choose M here: the module will be called rcar-isp. -config VIDEO_SH_VOU - tristate "SuperH VOU video output driver" - depends on V4L_PLATFORM_DRIVERS - depends on VIDEO_DEV && I2C - depends on ARCH_SHMOBILE || COMPILE_TEST - select VIDEOBUF2_DMA_CONTIG - help - Support for the Video Output Unit (VOU) on SuperH SoCs. - source "drivers/media/platform/renesas/rcar-vin/Kconfig" source "drivers/media/platform/renesas/rzg2l-cru/Kconfig" diff --git a/drivers/media/platform/renesas/Makefile b/drivers/media/platform/renesas/Makefile index 55854e8688870f..1ae7d825073df3 100644 --- a/drivers/media/platform/renesas/Makefile +++ b/drivers/media/platform/renesas/Makefile @@ -13,4 +13,3 @@ obj-$(CONFIG_VIDEO_RENESAS_CEU) += renesas-ceu.o obj-$(CONFIG_VIDEO_RENESAS_FCP) += rcar-fcp.o obj-$(CONFIG_VIDEO_RENESAS_FDP1) += rcar_fdp1.o obj-$(CONFIG_VIDEO_RENESAS_JPU) += rcar_jpu.o -obj-$(CONFIG_VIDEO_SH_VOU) += sh_vou.o diff --git a/drivers/media/platform/renesas/sh_vou.c b/drivers/media/platform/renesas/sh_vou.c deleted file mode 100644 index ca4310e26c49ee..00000000000000 --- a/drivers/media/platform/renesas/sh_vou.c +++ /dev/null @@ -1,1375 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * SuperH Video Output Unit (VOU) driver - * - * Copyright (C) 2010, Guennadi Liakhovetski - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -/* Mirror addresses are not available for all registers */ -#define VOUER 0 -#define VOUCR 4 -#define VOUSTR 8 -#define VOUVCR 0xc -#define VOUISR 0x10 -#define VOUBCR 0x14 -#define VOUDPR 0x18 -#define VOUDSR 0x1c -#define VOUVPR 0x20 -#define VOUIR 0x24 -#define VOUSRR 0x28 -#define VOUMSR 0x2c -#define VOUHIR 0x30 -#define VOUDFR 0x34 -#define VOUAD1R 0x38 -#define VOUAD2R 0x3c -#define VOUAIR 0x40 -#define VOUSWR 0x44 -#define VOURCR 0x48 -#define VOURPR 0x50 - -enum sh_vou_status { - SH_VOU_IDLE, - SH_VOU_INITIALISING, - SH_VOU_RUNNING, -}; - -#define VOU_MIN_IMAGE_WIDTH 16 -#define VOU_MAX_IMAGE_WIDTH 720 -#define VOU_MIN_IMAGE_HEIGHT 16 - -struct sh_vou_buffer { - struct vb2_v4l2_buffer vb; - struct list_head list; -}; - -static inline struct -sh_vou_buffer *to_sh_vou_buffer(struct vb2_v4l2_buffer *vb2) -{ - return container_of(vb2, struct sh_vou_buffer, vb); -} - -struct sh_vou_device { - struct v4l2_device v4l2_dev; - struct video_device vdev; - struct sh_vou_pdata *pdata; - spinlock_t lock; - void __iomem *base; - /* State information */ - struct v4l2_pix_format pix; - struct v4l2_rect rect; - struct list_head buf_list; - v4l2_std_id std; - int pix_idx; - struct vb2_queue queue; - struct sh_vou_buffer *active; - enum sh_vou_status status; - unsigned sequence; - struct mutex fop_lock; -}; - -/* Register access routines for sides A, B and mirror addresses */ -static void sh_vou_reg_a_write(struct sh_vou_device *vou_dev, unsigned int reg, - u32 value) -{ - __raw_writel(value, vou_dev->base + reg); -} - -static void sh_vou_reg_ab_write(struct sh_vou_device *vou_dev, unsigned int reg, - u32 value) -{ - __raw_writel(value, vou_dev->base + reg); - __raw_writel(value, vou_dev->base + reg + 0x1000); -} - -static void sh_vou_reg_m_write(struct sh_vou_device *vou_dev, unsigned int reg, - u32 value) -{ - __raw_writel(value, vou_dev->base + reg + 0x2000); -} - -static u32 sh_vou_reg_a_read(struct sh_vou_device *vou_dev, unsigned int reg) -{ - return __raw_readl(vou_dev->base + reg); -} - -static void sh_vou_reg_a_set(struct sh_vou_device *vou_dev, unsigned int reg, - u32 value, u32 mask) -{ - u32 old = __raw_readl(vou_dev->base + reg); - - value = (value & mask) | (old & ~mask); - __raw_writel(value, vou_dev->base + reg); -} - -static void sh_vou_reg_b_set(struct sh_vou_device *vou_dev, unsigned int reg, - u32 value, u32 mask) -{ - sh_vou_reg_a_set(vou_dev, reg + 0x1000, value, mask); -} - -static void sh_vou_reg_ab_set(struct sh_vou_device *vou_dev, unsigned int reg, - u32 value, u32 mask) -{ - sh_vou_reg_a_set(vou_dev, reg, value, mask); - sh_vou_reg_b_set(vou_dev, reg, value, mask); -} - -struct sh_vou_fmt { - u32 pfmt; - unsigned char bpp; - unsigned char bpl; - unsigned char rgb; - unsigned char yf; - unsigned char pkf; -}; - -/* Further pixel formats can be added */ -static struct sh_vou_fmt vou_fmt[] = { - { - .pfmt = V4L2_PIX_FMT_NV12, - .bpp = 12, - .bpl = 1, - .yf = 0, - .rgb = 0, - }, - { - .pfmt = V4L2_PIX_FMT_NV16, - .bpp = 16, - .bpl = 1, - .yf = 1, - .rgb = 0, - }, - { - .pfmt = V4L2_PIX_FMT_RGB24, - .bpp = 24, - .bpl = 3, - .pkf = 2, - .rgb = 1, - }, - { - .pfmt = V4L2_PIX_FMT_RGB565, - .bpp = 16, - .bpl = 2, - .pkf = 3, - .rgb = 1, - }, - { - .pfmt = V4L2_PIX_FMT_RGB565X, - .bpp = 16, - .bpl = 2, - .pkf = 3, - .rgb = 1, - }, -}; - -static void sh_vou_schedule_next(struct sh_vou_device *vou_dev, - struct vb2_v4l2_buffer *vbuf) -{ - dma_addr_t addr1, addr2; - - addr1 = vb2_dma_contig_plane_dma_addr(&vbuf->vb2_buf, 0); - switch (vou_dev->pix.pixelformat) { - case V4L2_PIX_FMT_NV12: - case V4L2_PIX_FMT_NV16: - addr2 = addr1 + vou_dev->pix.width * vou_dev->pix.height; - break; - default: - addr2 = 0; - } - - sh_vou_reg_m_write(vou_dev, VOUAD1R, addr1); - sh_vou_reg_m_write(vou_dev, VOUAD2R, addr2); -} - -static void sh_vou_stream_config(struct sh_vou_device *vou_dev) -{ - unsigned int row_coeff; -#ifdef __LITTLE_ENDIAN - u32 dataswap = 7; -#else - u32 dataswap = 0; -#endif - - switch (vou_dev->pix.pixelformat) { - default: - case V4L2_PIX_FMT_NV12: - case V4L2_PIX_FMT_NV16: - row_coeff = 1; - break; - case V4L2_PIX_FMT_RGB565: - dataswap ^= 1; - fallthrough; - case V4L2_PIX_FMT_RGB565X: - row_coeff = 2; - break; - case V4L2_PIX_FMT_RGB24: - row_coeff = 3; - break; - } - - sh_vou_reg_a_write(vou_dev, VOUSWR, dataswap); - sh_vou_reg_ab_write(vou_dev, VOUAIR, vou_dev->pix.width * row_coeff); -} - -/* Locking: caller holds fop_lock mutex */ -static int sh_vou_queue_setup(struct vb2_queue *vq, - unsigned int *nbuffers, unsigned int *nplanes, - unsigned int sizes[], struct device *alloc_devs[]) -{ - struct sh_vou_device *vou_dev = vb2_get_drv_priv(vq); - struct v4l2_pix_format *pix = &vou_dev->pix; - int bytes_per_line = vou_fmt[vou_dev->pix_idx].bpp * pix->width / 8; - - dev_dbg(vou_dev->v4l2_dev.dev, "%s()\n", __func__); - - if (*nplanes) - return sizes[0] < pix->height * bytes_per_line ? -EINVAL : 0; - *nplanes = 1; - sizes[0] = pix->height * bytes_per_line; - return 0; -} - -static int sh_vou_buf_prepare(struct vb2_buffer *vb) -{ - struct sh_vou_device *vou_dev = vb2_get_drv_priv(vb->vb2_queue); - struct v4l2_pix_format *pix = &vou_dev->pix; - unsigned bytes_per_line = vou_fmt[vou_dev->pix_idx].bpp * pix->width / 8; - unsigned size = pix->height * bytes_per_line; - - dev_dbg(vou_dev->v4l2_dev.dev, "%s()\n", __func__); - - if (vb2_plane_size(vb, 0) < size) { - /* User buffer too small */ - dev_warn(vou_dev->v4l2_dev.dev, "buffer too small (%lu < %u)\n", - vb2_plane_size(vb, 0), size); - return -EINVAL; - } - - vb2_set_plane_payload(vb, 0, size); - return 0; -} - -/* Locking: caller holds fop_lock mutex and vq->irqlock spinlock */ -static void sh_vou_buf_queue(struct vb2_buffer *vb) -{ - struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); - struct sh_vou_device *vou_dev = vb2_get_drv_priv(vb->vb2_queue); - struct sh_vou_buffer *shbuf = to_sh_vou_buffer(vbuf); - unsigned long flags; - - spin_lock_irqsave(&vou_dev->lock, flags); - list_add_tail(&shbuf->list, &vou_dev->buf_list); - spin_unlock_irqrestore(&vou_dev->lock, flags); -} - -static int sh_vou_start_streaming(struct vb2_queue *vq, unsigned int count) -{ - struct sh_vou_device *vou_dev = vb2_get_drv_priv(vq); - struct sh_vou_buffer *buf, *node; - int ret; - - vou_dev->sequence = 0; - ret = v4l2_device_call_until_err(&vou_dev->v4l2_dev, 0, - video, s_stream, 1); - if (ret < 0 && ret != -ENOIOCTLCMD) { - list_for_each_entry_safe(buf, node, &vou_dev->buf_list, list) { - vb2_buffer_done(&buf->vb.vb2_buf, - VB2_BUF_STATE_QUEUED); - list_del(&buf->list); - } - vou_dev->active = NULL; - return ret; - } - - buf = list_entry(vou_dev->buf_list.next, struct sh_vou_buffer, list); - - vou_dev->active = buf; - - /* Start from side A: we use mirror addresses, so, set B */ - sh_vou_reg_a_write(vou_dev, VOURPR, 1); - dev_dbg(vou_dev->v4l2_dev.dev, "%s: first buffer status 0x%x\n", - __func__, sh_vou_reg_a_read(vou_dev, VOUSTR)); - sh_vou_schedule_next(vou_dev, &buf->vb); - - buf = list_entry(buf->list.next, struct sh_vou_buffer, list); - - /* Second buffer - initialise register side B */ - sh_vou_reg_a_write(vou_dev, VOURPR, 0); - sh_vou_schedule_next(vou_dev, &buf->vb); - - /* Register side switching with frame VSYNC */ - sh_vou_reg_a_write(vou_dev, VOURCR, 5); - - sh_vou_stream_config(vou_dev); - /* Enable End-of-Frame (VSYNC) interrupts */ - sh_vou_reg_a_write(vou_dev, VOUIR, 0x10004); - - /* Two buffers on the queue - activate the hardware */ - vou_dev->status = SH_VOU_RUNNING; - sh_vou_reg_a_write(vou_dev, VOUER, 0x107); - return 0; -} - -static void sh_vou_stop_streaming(struct vb2_queue *vq) -{ - struct sh_vou_device *vou_dev = vb2_get_drv_priv(vq); - struct sh_vou_buffer *buf, *node; - unsigned long flags; - - v4l2_device_call_until_err(&vou_dev->v4l2_dev, 0, - video, s_stream, 0); - /* disable output */ - sh_vou_reg_a_set(vou_dev, VOUER, 0, 1); - /* ...but the current frame will complete */ - sh_vou_reg_a_set(vou_dev, VOUIR, 0, 0x30000); - msleep(50); - spin_lock_irqsave(&vou_dev->lock, flags); - list_for_each_entry_safe(buf, node, &vou_dev->buf_list, list) { - vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR); - list_del(&buf->list); - } - vou_dev->active = NULL; - spin_unlock_irqrestore(&vou_dev->lock, flags); -} - -static const struct vb2_ops sh_vou_qops = { - .queue_setup = sh_vou_queue_setup, - .buf_prepare = sh_vou_buf_prepare, - .buf_queue = sh_vou_buf_queue, - .start_streaming = sh_vou_start_streaming, - .stop_streaming = sh_vou_stop_streaming, - .wait_prepare = vb2_ops_wait_prepare, - .wait_finish = vb2_ops_wait_finish, -}; - -/* Video IOCTLs */ -static int sh_vou_querycap(struct file *file, void *priv, - struct v4l2_capability *cap) -{ - struct sh_vou_device *vou_dev = video_drvdata(file); - - dev_dbg(vou_dev->v4l2_dev.dev, "%s()\n", __func__); - - strscpy(cap->card, "SuperH VOU", sizeof(cap->card)); - strscpy(cap->driver, "sh-vou", sizeof(cap->driver)); - strscpy(cap->bus_info, "platform:sh-vou", sizeof(cap->bus_info)); - return 0; -} - -/* Enumerate formats, that the device can accept from the user */ -static int sh_vou_enum_fmt_vid_out(struct file *file, void *priv, - struct v4l2_fmtdesc *fmt) -{ - struct sh_vou_device *vou_dev = video_drvdata(file); - - if (fmt->index >= ARRAY_SIZE(vou_fmt)) - return -EINVAL; - - dev_dbg(vou_dev->v4l2_dev.dev, "%s()\n", __func__); - - fmt->pixelformat = vou_fmt[fmt->index].pfmt; - - return 0; -} - -static int sh_vou_g_fmt_vid_out(struct file *file, void *priv, - struct v4l2_format *fmt) -{ - struct sh_vou_device *vou_dev = video_drvdata(file); - - dev_dbg(vou_dev->v4l2_dev.dev, "%s()\n", __func__); - - fmt->type = V4L2_BUF_TYPE_VIDEO_OUTPUT; - fmt->fmt.pix = vou_dev->pix; - - return 0; -} - -static const unsigned char vou_scale_h_num[] = {1, 9, 2, 9, 4}; -static const unsigned char vou_scale_h_den[] = {1, 8, 1, 4, 1}; -static const unsigned char vou_scale_h_fld[] = {0, 2, 1, 3}; -static const unsigned char vou_scale_v_num[] = {1, 2, 4}; -static const unsigned char vou_scale_v_den[] = {1, 1, 1}; -static const unsigned char vou_scale_v_fld[] = {0, 1}; - -static void sh_vou_configure_geometry(struct sh_vou_device *vou_dev, - int pix_idx, int w_idx, int h_idx) -{ - struct sh_vou_fmt *fmt = vou_fmt + pix_idx; - unsigned int black_left, black_top, width_max, - frame_in_height, frame_out_height, frame_out_top; - struct v4l2_rect *rect = &vou_dev->rect; - struct v4l2_pix_format *pix = &vou_dev->pix; - u32 vouvcr = 0, dsr_h, dsr_v; - - if (vou_dev->std & V4L2_STD_525_60) { - width_max = 858; - /* height_max = 262; */ - } else { - width_max = 864; - /* height_max = 312; */ - } - - frame_in_height = pix->height / 2; - frame_out_height = rect->height / 2; - frame_out_top = rect->top / 2; - - /* - * Cropping scheme: max useful image is 720x480, and the total video - * area is 858x525 (NTSC) or 864x625 (PAL). AK8813 / 8814 starts - * sampling data beginning with fixed 276th (NTSC) / 288th (PAL) clock, - * of which the first 33 / 25 clocks HSYNC must be held active. This - * has to be configured in CR[HW]. 1 pixel equals 2 clock periods. - * This gives CR[HW] = 16 / 12, VPR[HVP] = 138 / 144, which gives - * exactly 858 - 138 = 864 - 144 = 720! We call the out-of-display area, - * beyond DSR, specified on the left and top by the VPR register "black - * pixels" and out-of-image area (DPR) "background pixels." We fix VPR - * at 138 / 144 : 20, because that's the HSYNC timing, that our first - * client requires, and that's exactly what leaves us 720 pixels for the - * image; we leave VPR[VVP] at default 20 for now, because the client - * doesn't seem to have any special requirements for it. Otherwise we - * could also set it to max - 240 = 22 / 72. Thus VPR depends only on - * the selected standard, and DPR and DSR are selected according to - * cropping. Q: how does the client detect the first valid line? Does - * HSYNC stay inactive during invalid (black) lines? - */ - black_left = width_max - VOU_MAX_IMAGE_WIDTH; - black_top = 20; - - dsr_h = rect->width + rect->left; - dsr_v = frame_out_height + frame_out_top; - - dev_dbg(vou_dev->v4l2_dev.dev, - "image %ux%u, black %u:%u, offset %u:%u, display %ux%u\n", - pix->width, frame_in_height, black_left, black_top, - rect->left, frame_out_top, dsr_h, dsr_v); - - /* VOUISR height - half of a frame height in frame mode */ - sh_vou_reg_ab_write(vou_dev, VOUISR, (pix->width << 16) | frame_in_height); - sh_vou_reg_ab_write(vou_dev, VOUVPR, (black_left << 16) | black_top); - sh_vou_reg_ab_write(vou_dev, VOUDPR, (rect->left << 16) | frame_out_top); - sh_vou_reg_ab_write(vou_dev, VOUDSR, (dsr_h << 16) | dsr_v); - - /* - * if necessary, we could set VOUHIR to - * max(black_left + dsr_h, width_max) here - */ - - if (w_idx) - vouvcr |= (1 << 15) | (vou_scale_h_fld[w_idx - 1] << 4); - if (h_idx) - vouvcr |= (1 << 14) | vou_scale_v_fld[h_idx - 1]; - - dev_dbg(vou_dev->v4l2_dev.dev, "0x%08x: scaling 0x%x\n", - fmt->pfmt, vouvcr); - - /* To produce a colour bar for testing set bit 23 of VOUVCR */ - sh_vou_reg_ab_write(vou_dev, VOUVCR, vouvcr); - sh_vou_reg_ab_write(vou_dev, VOUDFR, - fmt->pkf | (fmt->yf << 8) | (fmt->rgb << 16)); -} - -struct sh_vou_geometry { - struct v4l2_rect output; - unsigned int in_width; - unsigned int in_height; - int scale_idx_h; - int scale_idx_v; -}; - -/* - * Find input geometry, that we can use to produce output, closest to the - * requested rectangle, using VOU scaling - */ -static void vou_adjust_input(struct sh_vou_geometry *geo, v4l2_std_id std) -{ - /* The compiler cannot know, that best and idx will indeed be set */ - unsigned int best_err = UINT_MAX, best = 0, img_height_max; - int i, idx = 0; - - if (std & V4L2_STD_525_60) - img_height_max = 480; - else - img_height_max = 576; - - /* Image width must be a multiple of 4 */ - v4l_bound_align_image(&geo->in_width, - VOU_MIN_IMAGE_WIDTH, VOU_MAX_IMAGE_WIDTH, 2, - &geo->in_height, - VOU_MIN_IMAGE_HEIGHT, img_height_max, 1, 0); - - /* Select scales to come as close as possible to the output image */ - for (i = ARRAY_SIZE(vou_scale_h_num) - 1; i >= 0; i--) { - unsigned int err; - unsigned int found = geo->output.width * vou_scale_h_den[i] / - vou_scale_h_num[i]; - - if (found > VOU_MAX_IMAGE_WIDTH) - /* scales increase */ - break; - - err = abs(found - geo->in_width); - if (err < best_err) { - best_err = err; - idx = i; - best = found; - } - if (!err) - break; - } - - geo->in_width = best; - geo->scale_idx_h = idx; - - best_err = UINT_MAX; - - /* This loop can be replaced with one division */ - for (i = ARRAY_SIZE(vou_scale_v_num) - 1; i >= 0; i--) { - unsigned int err; - unsigned int found = geo->output.height * vou_scale_v_den[i] / - vou_scale_v_num[i]; - - if (found > img_height_max) - /* scales increase */ - break; - - err = abs(found - geo->in_height); - if (err < best_err) { - best_err = err; - idx = i; - best = found; - } - if (!err) - break; - } - - geo->in_height = best; - geo->scale_idx_v = idx; -} - -/* - * Find output geometry, that we can produce, using VOU scaling, closest to - * the requested rectangle - */ -static void vou_adjust_output(struct sh_vou_geometry *geo, v4l2_std_id std) -{ - unsigned int best_err = UINT_MAX, best = geo->in_width, - width_max, height_max, img_height_max; - int i, idx_h = 0, idx_v = 0; - - if (std & V4L2_STD_525_60) { - width_max = 858; - height_max = 262 * 2; - img_height_max = 480; - } else { - width_max = 864; - height_max = 312 * 2; - img_height_max = 576; - } - - /* Select scales to come as close as possible to the output image */ - for (i = 0; i < ARRAY_SIZE(vou_scale_h_num); i++) { - unsigned int err; - unsigned int found = geo->in_width * vou_scale_h_num[i] / - vou_scale_h_den[i]; - - if (found > VOU_MAX_IMAGE_WIDTH) - /* scales increase */ - break; - - err = abs(found - geo->output.width); - if (err < best_err) { - best_err = err; - idx_h = i; - best = found; - } - if (!err) - break; - } - - geo->output.width = best; - geo->scale_idx_h = idx_h; - if (geo->output.left + best > width_max) - geo->output.left = width_max - best; - - pr_debug("%s(): W %u * %u/%u = %u\n", __func__, geo->in_width, - vou_scale_h_num[idx_h], vou_scale_h_den[idx_h], best); - - best_err = UINT_MAX; - - /* This loop can be replaced with one division */ - for (i = 0; i < ARRAY_SIZE(vou_scale_v_num); i++) { - unsigned int err; - unsigned int found = geo->in_height * vou_scale_v_num[i] / - vou_scale_v_den[i]; - - if (found > img_height_max) - /* scales increase */ - break; - - err = abs(found - geo->output.height); - if (err < best_err) { - best_err = err; - idx_v = i; - best = found; - } - if (!err) - break; - } - - geo->output.height = best; - geo->scale_idx_v = idx_v; - if (geo->output.top + best > height_max) - geo->output.top = height_max - best; - - pr_debug("%s(): H %u * %u/%u = %u\n", __func__, geo->in_height, - vou_scale_v_num[idx_v], vou_scale_v_den[idx_v], best); -} - -static int sh_vou_try_fmt_vid_out(struct file *file, void *priv, - struct v4l2_format *fmt) -{ - struct sh_vou_device *vou_dev = video_drvdata(file); - struct v4l2_pix_format *pix = &fmt->fmt.pix; - unsigned int img_height_max; - int pix_idx; - - dev_dbg(vou_dev->v4l2_dev.dev, "%s()\n", __func__); - - pix->field = V4L2_FIELD_INTERLACED; - pix->colorspace = V4L2_COLORSPACE_SMPTE170M; - pix->ycbcr_enc = pix->quantization = 0; - - for (pix_idx = 0; pix_idx < ARRAY_SIZE(vou_fmt); pix_idx++) - if (vou_fmt[pix_idx].pfmt == pix->pixelformat) - break; - - if (pix_idx == ARRAY_SIZE(vou_fmt)) - return -EINVAL; - - if (vou_dev->std & V4L2_STD_525_60) - img_height_max = 480; - else - img_height_max = 576; - - v4l_bound_align_image(&pix->width, - VOU_MIN_IMAGE_WIDTH, VOU_MAX_IMAGE_WIDTH, 2, - &pix->height, - VOU_MIN_IMAGE_HEIGHT, img_height_max, 1, 0); - pix->bytesperline = pix->width * vou_fmt[pix_idx].bpl; - pix->sizeimage = pix->height * ((pix->width * vou_fmt[pix_idx].bpp) >> 3); - - return 0; -} - -static int sh_vou_set_fmt_vid_out(struct sh_vou_device *vou_dev, - struct v4l2_pix_format *pix) -{ - unsigned int img_height_max; - struct sh_vou_geometry geo; - struct v4l2_subdev_format format = { - .which = V4L2_SUBDEV_FORMAT_ACTIVE, - /* Revisit: is this the correct code? */ - .format.code = MEDIA_BUS_FMT_YUYV8_2X8, - .format.field = V4L2_FIELD_INTERLACED, - .format.colorspace = V4L2_COLORSPACE_SMPTE170M, - }; - struct v4l2_mbus_framefmt *mbfmt = &format.format; - int pix_idx; - int ret; - - if (vb2_is_busy(&vou_dev->queue)) - return -EBUSY; - - for (pix_idx = 0; pix_idx < ARRAY_SIZE(vou_fmt); pix_idx++) - if (vou_fmt[pix_idx].pfmt == pix->pixelformat) - break; - - geo.in_width = pix->width; - geo.in_height = pix->height; - geo.output = vou_dev->rect; - - vou_adjust_output(&geo, vou_dev->std); - - mbfmt->width = geo.output.width; - mbfmt->height = geo.output.height; - ret = v4l2_device_call_until_err(&vou_dev->v4l2_dev, 0, pad, - set_fmt, NULL, &format); - /* Must be implemented, so, don't check for -ENOIOCTLCMD */ - if (ret < 0) - return ret; - - dev_dbg(vou_dev->v4l2_dev.dev, "%s(): %ux%u -> %ux%u\n", __func__, - geo.output.width, geo.output.height, mbfmt->width, mbfmt->height); - - if (vou_dev->std & V4L2_STD_525_60) - img_height_max = 480; - else - img_height_max = 576; - - /* Sanity checks */ - if ((unsigned)mbfmt->width > VOU_MAX_IMAGE_WIDTH || - (unsigned)mbfmt->height > img_height_max || - mbfmt->code != MEDIA_BUS_FMT_YUYV8_2X8) - return -EIO; - - if (mbfmt->width != geo.output.width || - mbfmt->height != geo.output.height) { - geo.output.width = mbfmt->width; - geo.output.height = mbfmt->height; - - vou_adjust_input(&geo, vou_dev->std); - } - - /* We tried to preserve output rectangle, but it could have changed */ - vou_dev->rect = geo.output; - pix->width = geo.in_width; - pix->height = geo.in_height; - - dev_dbg(vou_dev->v4l2_dev.dev, "%s(): %ux%u\n", __func__, - pix->width, pix->height); - - vou_dev->pix_idx = pix_idx; - - vou_dev->pix = *pix; - - sh_vou_configure_geometry(vou_dev, pix_idx, - geo.scale_idx_h, geo.scale_idx_v); - - return 0; -} - -static int sh_vou_s_fmt_vid_out(struct file *file, void *priv, - struct v4l2_format *fmt) -{ - struct sh_vou_device *vou_dev = video_drvdata(file); - int ret = sh_vou_try_fmt_vid_out(file, priv, fmt); - - if (ret) - return ret; - return sh_vou_set_fmt_vid_out(vou_dev, &fmt->fmt.pix); -} - -static int sh_vou_enum_output(struct file *file, void *fh, - struct v4l2_output *a) -{ - struct sh_vou_device *vou_dev = video_drvdata(file); - - if (a->index) - return -EINVAL; - strscpy(a->name, "Video Out", sizeof(a->name)); - a->type = V4L2_OUTPUT_TYPE_ANALOG; - a->std = vou_dev->vdev.tvnorms; - return 0; -} - -static int sh_vou_g_output(struct file *file, void *fh, unsigned int *i) -{ - *i = 0; - return 0; -} - -static int sh_vou_s_output(struct file *file, void *fh, unsigned int i) -{ - return i ? -EINVAL : 0; -} - -static u32 sh_vou_ntsc_mode(enum sh_vou_bus_fmt bus_fmt) -{ - switch (bus_fmt) { - default: - pr_warn("%s(): Invalid bus-format code %d, using default 8-bit\n", - __func__, bus_fmt); - fallthrough; - case SH_VOU_BUS_8BIT: - return 1; - case SH_VOU_BUS_16BIT: - return 0; - case SH_VOU_BUS_BT656: - return 3; - } -} - -static int sh_vou_s_std(struct file *file, void *priv, v4l2_std_id std_id) -{ - struct sh_vou_device *vou_dev = video_drvdata(file); - int ret; - - dev_dbg(vou_dev->v4l2_dev.dev, "%s(): 0x%llx\n", __func__, std_id); - - if (std_id == vou_dev->std) - return 0; - - if (vb2_is_busy(&vou_dev->queue)) - return -EBUSY; - - ret = v4l2_device_call_until_err(&vou_dev->v4l2_dev, 0, video, - s_std_output, std_id); - /* Shall we continue, if the subdev doesn't support .s_std_output()? */ - if (ret < 0 && ret != -ENOIOCTLCMD) - return ret; - - vou_dev->rect.top = vou_dev->rect.left = 0; - vou_dev->rect.width = VOU_MAX_IMAGE_WIDTH; - if (std_id & V4L2_STD_525_60) { - sh_vou_reg_ab_set(vou_dev, VOUCR, - sh_vou_ntsc_mode(vou_dev->pdata->bus_fmt) << 29, 7 << 29); - vou_dev->rect.height = 480; - } else { - sh_vou_reg_ab_set(vou_dev, VOUCR, 5 << 29, 7 << 29); - vou_dev->rect.height = 576; - } - - vou_dev->pix.width = vou_dev->rect.width; - vou_dev->pix.height = vou_dev->rect.height; - vou_dev->pix.bytesperline = - vou_dev->pix.width * vou_fmt[vou_dev->pix_idx].bpl; - vou_dev->pix.sizeimage = vou_dev->pix.height * - ((vou_dev->pix.width * vou_fmt[vou_dev->pix_idx].bpp) >> 3); - vou_dev->std = std_id; - sh_vou_set_fmt_vid_out(vou_dev, &vou_dev->pix); - - return 0; -} - -static int sh_vou_g_std(struct file *file, void *priv, v4l2_std_id *std) -{ - struct sh_vou_device *vou_dev = video_drvdata(file); - - dev_dbg(vou_dev->v4l2_dev.dev, "%s()\n", __func__); - - *std = vou_dev->std; - - return 0; -} - -static int sh_vou_log_status(struct file *file, void *priv) -{ - struct sh_vou_device *vou_dev = video_drvdata(file); - - pr_info("VOUER: 0x%08x\n", sh_vou_reg_a_read(vou_dev, VOUER)); - pr_info("VOUCR: 0x%08x\n", sh_vou_reg_a_read(vou_dev, VOUCR)); - pr_info("VOUSTR: 0x%08x\n", sh_vou_reg_a_read(vou_dev, VOUSTR)); - pr_info("VOUVCR: 0x%08x\n", sh_vou_reg_a_read(vou_dev, VOUVCR)); - pr_info("VOUISR: 0x%08x\n", sh_vou_reg_a_read(vou_dev, VOUISR)); - pr_info("VOUBCR: 0x%08x\n", sh_vou_reg_a_read(vou_dev, VOUBCR)); - pr_info("VOUDPR: 0x%08x\n", sh_vou_reg_a_read(vou_dev, VOUDPR)); - pr_info("VOUDSR: 0x%08x\n", sh_vou_reg_a_read(vou_dev, VOUDSR)); - pr_info("VOUVPR: 0x%08x\n", sh_vou_reg_a_read(vou_dev, VOUVPR)); - pr_info("VOUIR: 0x%08x\n", sh_vou_reg_a_read(vou_dev, VOUIR)); - pr_info("VOUSRR: 0x%08x\n", sh_vou_reg_a_read(vou_dev, VOUSRR)); - pr_info("VOUMSR: 0x%08x\n", sh_vou_reg_a_read(vou_dev, VOUMSR)); - pr_info("VOUHIR: 0x%08x\n", sh_vou_reg_a_read(vou_dev, VOUHIR)); - pr_info("VOUDFR: 0x%08x\n", sh_vou_reg_a_read(vou_dev, VOUDFR)); - pr_info("VOUAD1R: 0x%08x\n", sh_vou_reg_a_read(vou_dev, VOUAD1R)); - pr_info("VOUAD2R: 0x%08x\n", sh_vou_reg_a_read(vou_dev, VOUAD2R)); - pr_info("VOUAIR: 0x%08x\n", sh_vou_reg_a_read(vou_dev, VOUAIR)); - pr_info("VOUSWR: 0x%08x\n", sh_vou_reg_a_read(vou_dev, VOUSWR)); - pr_info("VOURCR: 0x%08x\n", sh_vou_reg_a_read(vou_dev, VOURCR)); - pr_info("VOURPR: 0x%08x\n", sh_vou_reg_a_read(vou_dev, VOURPR)); - return 0; -} - -static int sh_vou_g_selection(struct file *file, void *fh, - struct v4l2_selection *sel) -{ - struct sh_vou_device *vou_dev = video_drvdata(file); - - if (sel->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) - return -EINVAL; - switch (sel->target) { - case V4L2_SEL_TGT_COMPOSE: - sel->r = vou_dev->rect; - break; - case V4L2_SEL_TGT_COMPOSE_DEFAULT: - case V4L2_SEL_TGT_COMPOSE_BOUNDS: - sel->r.left = 0; - sel->r.top = 0; - sel->r.width = VOU_MAX_IMAGE_WIDTH; - if (vou_dev->std & V4L2_STD_525_60) - sel->r.height = 480; - else - sel->r.height = 576; - break; - default: - return -EINVAL; - } - return 0; -} - -/* Assume a dull encoder, do all the work ourselves. */ -static int sh_vou_s_selection(struct file *file, void *fh, - struct v4l2_selection *sel) -{ - struct v4l2_rect *rect = &sel->r; - struct sh_vou_device *vou_dev = video_drvdata(file); - struct v4l2_subdev_selection sd_sel = { - .which = V4L2_SUBDEV_FORMAT_ACTIVE, - .target = V4L2_SEL_TGT_COMPOSE, - }; - struct v4l2_pix_format *pix = &vou_dev->pix; - struct sh_vou_geometry geo; - struct v4l2_subdev_format format = { - .which = V4L2_SUBDEV_FORMAT_ACTIVE, - /* Revisit: is this the correct code? */ - .format.code = MEDIA_BUS_FMT_YUYV8_2X8, - .format.field = V4L2_FIELD_INTERLACED, - .format.colorspace = V4L2_COLORSPACE_SMPTE170M, - }; - unsigned int img_height_max; - int ret; - - if (sel->type != V4L2_BUF_TYPE_VIDEO_OUTPUT || - sel->target != V4L2_SEL_TGT_COMPOSE) - return -EINVAL; - - if (vb2_is_busy(&vou_dev->queue)) - return -EBUSY; - - if (vou_dev->std & V4L2_STD_525_60) - img_height_max = 480; - else - img_height_max = 576; - - v4l_bound_align_image(&rect->width, - VOU_MIN_IMAGE_WIDTH, VOU_MAX_IMAGE_WIDTH, 1, - &rect->height, - VOU_MIN_IMAGE_HEIGHT, img_height_max, 1, 0); - - if (rect->width + rect->left > VOU_MAX_IMAGE_WIDTH) - rect->left = VOU_MAX_IMAGE_WIDTH - rect->width; - - if (rect->height + rect->top > img_height_max) - rect->top = img_height_max - rect->height; - - geo.output = *rect; - geo.in_width = pix->width; - geo.in_height = pix->height; - - /* Configure the encoder one-to-one, position at 0, ignore errors */ - sd_sel.r.width = geo.output.width; - sd_sel.r.height = geo.output.height; - /* - * We first issue a S_SELECTION, so that the subsequent S_FMT delivers the - * final encoder configuration. - */ - v4l2_device_call_until_err(&vou_dev->v4l2_dev, 0, pad, - set_selection, NULL, &sd_sel); - format.format.width = geo.output.width; - format.format.height = geo.output.height; - ret = v4l2_device_call_until_err(&vou_dev->v4l2_dev, 0, pad, - set_fmt, NULL, &format); - /* Must be implemented, so, don't check for -ENOIOCTLCMD */ - if (ret < 0) - return ret; - - /* Sanity checks */ - if ((unsigned)format.format.width > VOU_MAX_IMAGE_WIDTH || - (unsigned)format.format.height > img_height_max || - format.format.code != MEDIA_BUS_FMT_YUYV8_2X8) - return -EIO; - - geo.output.width = format.format.width; - geo.output.height = format.format.height; - - /* - * No down-scaling. According to the API, current call has precedence: - * https://linuxtv.org/downloads/v4l-dvb-apis/uapi/v4l/crop.html#cropping-structures - */ - vou_adjust_input(&geo, vou_dev->std); - - /* We tried to preserve output rectangle, but it could have changed */ - vou_dev->rect = geo.output; - pix->width = geo.in_width; - pix->height = geo.in_height; - - sh_vou_configure_geometry(vou_dev, vou_dev->pix_idx, - geo.scale_idx_h, geo.scale_idx_v); - - return 0; -} - -static irqreturn_t sh_vou_isr(int irq, void *dev_id) -{ - struct sh_vou_device *vou_dev = dev_id; - static unsigned long j; - struct sh_vou_buffer *vb; - static int cnt; - u32 irq_status = sh_vou_reg_a_read(vou_dev, VOUIR), masked; - u32 vou_status = sh_vou_reg_a_read(vou_dev, VOUSTR); - - if (!(irq_status & 0x300)) { - if (printk_timed_ratelimit(&j, 500)) - dev_warn(vou_dev->v4l2_dev.dev, "IRQ status 0x%x!\n", - irq_status); - return IRQ_NONE; - } - - spin_lock(&vou_dev->lock); - if (!vou_dev->active || list_empty(&vou_dev->buf_list)) { - if (printk_timed_ratelimit(&j, 500)) - dev_warn(vou_dev->v4l2_dev.dev, - "IRQ without active buffer: %x!\n", irq_status); - /* Just ack: buf_release will disable further interrupts */ - sh_vou_reg_a_set(vou_dev, VOUIR, 0, 0x300); - spin_unlock(&vou_dev->lock); - return IRQ_HANDLED; - } - - masked = ~(0x300 & irq_status) & irq_status & 0x30304; - dev_dbg(vou_dev->v4l2_dev.dev, - "IRQ status 0x%x -> 0x%x, VOU status 0x%x, cnt %d\n", - irq_status, masked, vou_status, cnt); - - cnt++; - /* side = vou_status & 0x10000; */ - - /* Clear only set interrupts */ - sh_vou_reg_a_write(vou_dev, VOUIR, masked); - - vb = vou_dev->active; - if (list_is_singular(&vb->list)) { - /* Keep cycling while no next buffer is available */ - sh_vou_schedule_next(vou_dev, &vb->vb); - spin_unlock(&vou_dev->lock); - return IRQ_HANDLED; - } - - list_del(&vb->list); - - vb->vb.vb2_buf.timestamp = ktime_get_ns(); - vb->vb.sequence = vou_dev->sequence++; - vb->vb.field = V4L2_FIELD_INTERLACED; - vb2_buffer_done(&vb->vb.vb2_buf, VB2_BUF_STATE_DONE); - - vou_dev->active = list_entry(vou_dev->buf_list.next, - struct sh_vou_buffer, list); - - if (list_is_singular(&vou_dev->buf_list)) { - /* Keep cycling while no next buffer is available */ - sh_vou_schedule_next(vou_dev, &vou_dev->active->vb); - } else { - struct sh_vou_buffer *new = list_entry(vou_dev->active->list.next, - struct sh_vou_buffer, list); - sh_vou_schedule_next(vou_dev, &new->vb); - } - - spin_unlock(&vou_dev->lock); - - return IRQ_HANDLED; -} - -static int sh_vou_hw_init(struct sh_vou_device *vou_dev) -{ - struct sh_vou_pdata *pdata = vou_dev->pdata; - u32 voucr = sh_vou_ntsc_mode(pdata->bus_fmt) << 29; - int i = 100; - - /* Disable all IRQs */ - sh_vou_reg_a_write(vou_dev, VOUIR, 0); - - /* Reset VOU interfaces - registers unaffected */ - sh_vou_reg_a_write(vou_dev, VOUSRR, 0x101); - while (--i && (sh_vou_reg_a_read(vou_dev, VOUSRR) & 0x101)) - udelay(1); - - if (!i) - return -ETIMEDOUT; - - dev_dbg(vou_dev->v4l2_dev.dev, "Reset took %dus\n", 100 - i); - - if (pdata->flags & SH_VOU_PCLK_FALLING) - voucr |= 1 << 28; - if (pdata->flags & SH_VOU_HSYNC_LOW) - voucr |= 1 << 27; - if (pdata->flags & SH_VOU_VSYNC_LOW) - voucr |= 1 << 26; - sh_vou_reg_ab_set(vou_dev, VOUCR, voucr, 0xfc000000); - - /* Manual register side switching at first */ - sh_vou_reg_a_write(vou_dev, VOURCR, 4); - /* Default - fixed HSYNC length, can be made configurable is required */ - sh_vou_reg_ab_write(vou_dev, VOUMSR, 0x800000); - - sh_vou_set_fmt_vid_out(vou_dev, &vou_dev->pix); - - return 0; -} - -/* File operations */ -static int sh_vou_open(struct file *file) -{ - struct sh_vou_device *vou_dev = video_drvdata(file); - int err; - - if (mutex_lock_interruptible(&vou_dev->fop_lock)) - return -ERESTARTSYS; - - err = v4l2_fh_open(file); - if (err) - goto done_open; - if (v4l2_fh_is_singular_file(file) && - vou_dev->status == SH_VOU_INITIALISING) { - /* First open */ - err = pm_runtime_resume_and_get(vou_dev->v4l2_dev.dev); - if (err < 0) { - v4l2_fh_release(file); - goto done_open; - } - err = sh_vou_hw_init(vou_dev); - if (err < 0) { - pm_runtime_put(vou_dev->v4l2_dev.dev); - v4l2_fh_release(file); - } else { - vou_dev->status = SH_VOU_IDLE; - } - } -done_open: - mutex_unlock(&vou_dev->fop_lock); - return err; -} - -static int sh_vou_release(struct file *file) -{ - struct sh_vou_device *vou_dev = video_drvdata(file); - bool is_last; - - mutex_lock(&vou_dev->fop_lock); - is_last = v4l2_fh_is_singular_file(file); - _vb2_fop_release(file, NULL); - if (is_last) { - /* Last close */ - vou_dev->status = SH_VOU_INITIALISING; - sh_vou_reg_a_set(vou_dev, VOUER, 0, 0x101); - pm_runtime_put(vou_dev->v4l2_dev.dev); - } - mutex_unlock(&vou_dev->fop_lock); - return 0; -} - -/* sh_vou display ioctl operations */ -static const struct v4l2_ioctl_ops sh_vou_ioctl_ops = { - .vidioc_querycap = sh_vou_querycap, - .vidioc_enum_fmt_vid_out = sh_vou_enum_fmt_vid_out, - .vidioc_g_fmt_vid_out = sh_vou_g_fmt_vid_out, - .vidioc_s_fmt_vid_out = sh_vou_s_fmt_vid_out, - .vidioc_try_fmt_vid_out = sh_vou_try_fmt_vid_out, - .vidioc_reqbufs = vb2_ioctl_reqbufs, - .vidioc_create_bufs = vb2_ioctl_create_bufs, - .vidioc_querybuf = vb2_ioctl_querybuf, - .vidioc_qbuf = vb2_ioctl_qbuf, - .vidioc_dqbuf = vb2_ioctl_dqbuf, - .vidioc_prepare_buf = vb2_ioctl_prepare_buf, - .vidioc_streamon = vb2_ioctl_streamon, - .vidioc_streamoff = vb2_ioctl_streamoff, - .vidioc_expbuf = vb2_ioctl_expbuf, - .vidioc_g_output = sh_vou_g_output, - .vidioc_s_output = sh_vou_s_output, - .vidioc_enum_output = sh_vou_enum_output, - .vidioc_s_std = sh_vou_s_std, - .vidioc_g_std = sh_vou_g_std, - .vidioc_g_selection = sh_vou_g_selection, - .vidioc_s_selection = sh_vou_s_selection, - .vidioc_log_status = sh_vou_log_status, -}; - -static const struct v4l2_file_operations sh_vou_fops = { - .owner = THIS_MODULE, - .open = sh_vou_open, - .release = sh_vou_release, - .unlocked_ioctl = video_ioctl2, - .mmap = vb2_fop_mmap, - .poll = vb2_fop_poll, - .write = vb2_fop_write, -}; - -static const struct video_device sh_vou_video_template = { - .name = "sh_vou", - .fops = &sh_vou_fops, - .ioctl_ops = &sh_vou_ioctl_ops, - .tvnorms = V4L2_STD_525_60, /* PAL only supported in 8-bit non-bt656 mode */ - .vfl_dir = VFL_DIR_TX, - .device_caps = V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_READWRITE | - V4L2_CAP_STREAMING, -}; - -static int sh_vou_probe(struct platform_device *pdev) -{ - struct sh_vou_pdata *vou_pdata = pdev->dev.platform_data; - struct v4l2_rect *rect; - struct v4l2_pix_format *pix; - struct i2c_adapter *i2c_adap; - struct video_device *vdev; - struct sh_vou_device *vou_dev; - struct resource *reg_res; - struct v4l2_subdev *subdev; - struct vb2_queue *q; - int irq, ret; - - reg_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - irq = platform_get_irq(pdev, 0); - - if (!vou_pdata || !reg_res || irq <= 0) { - dev_err(&pdev->dev, "Insufficient VOU platform information.\n"); - return -ENODEV; - } - - vou_dev = devm_kzalloc(&pdev->dev, sizeof(*vou_dev), GFP_KERNEL); - if (!vou_dev) - return -ENOMEM; - - INIT_LIST_HEAD(&vou_dev->buf_list); - spin_lock_init(&vou_dev->lock); - mutex_init(&vou_dev->fop_lock); - vou_dev->pdata = vou_pdata; - vou_dev->status = SH_VOU_INITIALISING; - vou_dev->pix_idx = 1; - - rect = &vou_dev->rect; - pix = &vou_dev->pix; - - /* Fill in defaults */ - vou_dev->std = V4L2_STD_NTSC_M; - rect->left = 0; - rect->top = 0; - rect->width = VOU_MAX_IMAGE_WIDTH; - rect->height = 480; - pix->width = VOU_MAX_IMAGE_WIDTH; - pix->height = 480; - pix->pixelformat = V4L2_PIX_FMT_NV16; - pix->field = V4L2_FIELD_INTERLACED; - pix->bytesperline = VOU_MAX_IMAGE_WIDTH; - pix->sizeimage = VOU_MAX_IMAGE_WIDTH * 2 * 480; - pix->colorspace = V4L2_COLORSPACE_SMPTE170M; - - vou_dev->base = devm_ioremap_resource(&pdev->dev, reg_res); - if (IS_ERR(vou_dev->base)) - return PTR_ERR(vou_dev->base); - - ret = devm_request_irq(&pdev->dev, irq, sh_vou_isr, 0, "vou", vou_dev); - if (ret < 0) - return ret; - - ret = v4l2_device_register(&pdev->dev, &vou_dev->v4l2_dev); - if (ret < 0) { - dev_err(&pdev->dev, "Error registering v4l2 device\n"); - return ret; - } - - vdev = &vou_dev->vdev; - *vdev = sh_vou_video_template; - if (vou_pdata->bus_fmt == SH_VOU_BUS_8BIT) - vdev->tvnorms |= V4L2_STD_PAL; - vdev->v4l2_dev = &vou_dev->v4l2_dev; - vdev->release = video_device_release_empty; - vdev->lock = &vou_dev->fop_lock; - - video_set_drvdata(vdev, vou_dev); - - /* Initialize the vb2 queue */ - q = &vou_dev->queue; - q->type = V4L2_BUF_TYPE_VIDEO_OUTPUT; - q->io_modes = VB2_MMAP | VB2_DMABUF | VB2_WRITE; - q->drv_priv = vou_dev; - q->buf_struct_size = sizeof(struct sh_vou_buffer); - q->ops = &sh_vou_qops; - q->mem_ops = &vb2_dma_contig_memops; - q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; - q->min_buffers_needed = 2; - q->lock = &vou_dev->fop_lock; - q->dev = &pdev->dev; - ret = vb2_queue_init(q); - if (ret) - goto ei2cgadap; - - vdev->queue = q; - INIT_LIST_HEAD(&vou_dev->buf_list); - - pm_runtime_enable(&pdev->dev); - pm_runtime_resume(&pdev->dev); - - i2c_adap = i2c_get_adapter(vou_pdata->i2c_adap); - if (!i2c_adap) { - ret = -ENODEV; - goto ei2cgadap; - } - - ret = sh_vou_hw_init(vou_dev); - if (ret < 0) - goto ereset; - - subdev = v4l2_i2c_new_subdev_board(&vou_dev->v4l2_dev, i2c_adap, - vou_pdata->board_info, NULL); - if (!subdev) { - ret = -ENOMEM; - goto ei2cnd; - } - - ret = video_register_device(vdev, VFL_TYPE_VIDEO, -1); - if (ret < 0) - goto evregdev; - - return 0; - -evregdev: -ei2cnd: -ereset: - i2c_put_adapter(i2c_adap); -ei2cgadap: - pm_runtime_disable(&pdev->dev); - v4l2_device_unregister(&vou_dev->v4l2_dev); - return ret; -} - -static int sh_vou_remove(struct platform_device *pdev) -{ - struct v4l2_device *v4l2_dev = platform_get_drvdata(pdev); - struct sh_vou_device *vou_dev = container_of(v4l2_dev, - struct sh_vou_device, v4l2_dev); - struct v4l2_subdev *sd = list_entry(v4l2_dev->subdevs.next, - struct v4l2_subdev, list); - struct i2c_client *client = v4l2_get_subdevdata(sd); - - pm_runtime_disable(&pdev->dev); - video_unregister_device(&vou_dev->vdev); - i2c_put_adapter(client->adapter); - v4l2_device_unregister(&vou_dev->v4l2_dev); - return 0; -} - -static struct platform_driver sh_vou = { - .remove = sh_vou_remove, - .driver = { - .name = "sh-vou", - }, -}; - -module_platform_driver_probe(sh_vou, sh_vou_probe); - -MODULE_DESCRIPTION("SuperH VOU driver"); -MODULE_AUTHOR("Guennadi Liakhovetski "); -MODULE_LICENSE("GPL v2"); -MODULE_VERSION("0.1.0"); -MODULE_ALIAS("platform:sh-vou");