diff options
Diffstat (limited to 'target/linux/oxnas/files/drivers')
10 files changed, 385 insertions, 2492 deletions
diff --git a/target/linux/oxnas/files/drivers/ata/sata_oxnas.c b/target/linux/oxnas/files/drivers/ata/sata_oxnas.c index 291a06f959..64afa728a1 100644 --- a/target/linux/oxnas/files/drivers/ata/sata_oxnas.c +++ b/target/linux/oxnas/files/drivers/ata/sata_oxnas.c @@ -29,7 +29,35 @@ #include <linux/clk.h> #include <linux/reset.h> -#include <mach/utils.h> +#include <linux/io.h> +#include <linux/sizes.h> + +static inline void oxnas_register_clear_mask(void __iomem *p, unsigned mask) +{ + u32 val = readl_relaxed(p); + + val &= ~mask; + writel_relaxed(val, p); +} + +static inline void oxnas_register_set_mask(void __iomem *p, unsigned mask) +{ + u32 val = readl_relaxed(p); + + val |= mask; + writel_relaxed(val, p); +} + +static inline void oxnas_register_value_mask(void __iomem *p, + unsigned mask, unsigned new_value) +{ + /* TODO sanity check mask & new_value = new_value */ + u32 val = readl_relaxed(p); + + val &= ~mask; + val |= new_value; + writel_relaxed(val, p); +} /* sgdma request structure */ struct sgdma_request { @@ -848,7 +876,7 @@ wait_for_lock: * list so want to give reentrant accessors a chance to get * access ASAP */ - if (!list_empty(&hd->scsi_wait_queue.task_list)) + if (!list_empty(&hd->scsi_wait_queue.head)) wake_up(&hd->scsi_wait_queue); } @@ -867,7 +895,7 @@ int sata_core_has_fast_waiters(struct ata_host *ah) struct sata_oxnas_host_priv *hd = ah->private_data; spin_lock_irqsave(&hd->core_lock, flags); - has_waiters = !list_empty(&hd->fast_wait_queue.task_list); + has_waiters = !list_empty(&hd->fast_wait_queue.head); spin_unlock_irqrestore(&hd->core_lock, flags); return has_waiters; @@ -882,7 +910,7 @@ int sata_core_has_scsi_waiters(struct ata_host *ah) spin_lock_irqsave(&hd->core_lock, flags); has_waiters = hd->scsi_nonblocking_attempts || - !list_empty(&hd->scsi_wait_queue.task_list); + !list_empty(&hd->scsi_wait_queue.head); spin_unlock_irqrestore(&hd->core_lock, flags); return has_waiters; @@ -954,7 +982,7 @@ static void sata_oxnas_release_hw(struct ata_port *ap) hd->locker_uid = 0; hd->core_locked = 0; released = 1; - wake_up(!list_empty(&hd->scsi_wait_queue.task_list) ? + wake_up(!list_empty(&hd->scsi_wait_queue.head) ? &hd->scsi_wait_queue : &hd->fast_wait_queue); } diff --git a/target/linux/oxnas/files/drivers/clk/clk-oxnas.c b/target/linux/oxnas/files/drivers/clk/clk-oxnas.c deleted file mode 100644 index 4dc6c44992..0000000000 --- a/target/linux/oxnas/files/drivers/clk/clk-oxnas.c +++ /dev/null @@ -1,297 +0,0 @@ -/* - * Copyright (C) 2010 Broadcom - * Copyright (C) 2012 Stephen Warren - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#include <linux/clk.h> -#include <linux/clkdev.h> -#include <linux/clk-provider.h> -#include <linux/of.h> -#include <linux/delay.h> -#include <linux/stringify.h> -#include <linux/reset.h> -#include <linux/io.h> -#include <mach/hardware.h> -#include <mach/utils.h> - -#define MHZ (1000 * 1000) - -struct clk_oxnas_pllb { - struct clk_hw hw; - struct device_node *devnode; - struct reset_control *rstc; -}; - -#define to_clk_oxnas_pllb(_hw) container_of(_hw, struct clk_oxnas_pllb, hw) - -static unsigned long plla_clk_recalc_rate(struct clk_hw *hw, - unsigned long parent_rate) -{ - unsigned long fin = parent_rate; - unsigned long pll0; - unsigned long fbdiv, refdiv, outdiv; - - pll0 = readl_relaxed(SYS_CTRL_PLLA_CTRL0); - refdiv = (pll0 >> PLLA_REFDIV_SHIFT) & PLLA_REFDIV_MASK; - refdiv += 1; - outdiv = (pll0 >> PLLA_OUTDIV_SHIFT) & PLLA_OUTDIV_MASK; - outdiv += 1; - fbdiv = readl_relaxed(SYS_CTRL_PLLA_CTRL1); - - /* seems we will not be here when pll is bypassed, so ignore this - * case */ - - return fin / MHZ * fbdiv / (refdiv * outdiv) / 32768 * MHZ; -} - -static const char *pll_clk_parents[] = { - "oscillator", -}; - -static struct clk_ops plla_ops = { - .recalc_rate = plla_clk_recalc_rate, -}; - -static struct clk_init_data clk_plla_init = { - .name = "plla", - .ops = &plla_ops, - .parent_names = pll_clk_parents, - .num_parents = ARRAY_SIZE(pll_clk_parents), -}; - -static struct clk_hw plla_hw = { - .init = &clk_plla_init, -}; - -static int pllb_clk_is_prepared(struct clk_hw *hw) -{ - struct clk_oxnas_pllb *pllb = to_clk_oxnas_pllb(hw); - - return !!pllb->rstc; -} - -static int pllb_clk_prepare(struct clk_hw *hw) -{ - struct clk_oxnas_pllb *pllb = to_clk_oxnas_pllb(hw); - - pllb->rstc = of_reset_control_get(pllb->devnode, NULL); - - return IS_ERR(pllb->rstc) ? PTR_ERR(pllb->rstc) : 0; -} - -static void pllb_clk_unprepare(struct clk_hw *hw) -{ - struct clk_oxnas_pllb *pllb = to_clk_oxnas_pllb(hw); - - BUG_ON(IS_ERR(pllb->rstc)); - - reset_control_put(pllb->rstc); - pllb->rstc = NULL; -} - -static int pllb_clk_enable(struct clk_hw *hw) -{ - struct clk_oxnas_pllb *pllb = to_clk_oxnas_pllb(hw); - - BUG_ON(IS_ERR(pllb->rstc)); - - /* put PLL into bypass */ - oxnas_register_set_mask(SEC_CTRL_PLLB_CTRL0, BIT(PLLB_BYPASS)); - wmb(); - udelay(10); - reset_control_assert(pllb->rstc); - udelay(10); - /* set PLL B control information */ - writel((1 << PLLB_ENSAT) | (1 << PLLB_OUTDIV) | (2 << PLLB_REFDIV), - SEC_CTRL_PLLB_CTRL0); - reset_control_deassert(pllb->rstc); - udelay(100); - oxnas_register_clear_mask(SEC_CTRL_PLLB_CTRL0, BIT(PLLB_BYPASS)); - - return 0; -} - -static void pllb_clk_disable(struct clk_hw *hw) -{ - struct clk_oxnas_pllb *pllb = to_clk_oxnas_pllb(hw); - - BUG_ON(IS_ERR(pllb->rstc)); - - /* put PLL into bypass */ - oxnas_register_set_mask(SEC_CTRL_PLLB_CTRL0, BIT(PLLB_BYPASS)); - wmb(); - udelay(10); - - reset_control_assert(pllb->rstc); -} - -static struct clk_ops pllb_ops = { - .prepare = pllb_clk_prepare, - .unprepare = pllb_clk_unprepare, - .is_prepared = pllb_clk_is_prepared, - .enable = pllb_clk_enable, - .disable = pllb_clk_disable, -}; - -static struct clk_init_data clk_pllb_init = { - .name = "pllb", - .ops = &pllb_ops, - .parent_names = pll_clk_parents, - .num_parents = ARRAY_SIZE(pll_clk_parents), -}; - - -/* standard gate clock */ -struct clk_std { - struct clk_hw hw; - signed char bit; -}; - -#define NUM_STD_CLKS 17 -#define to_stdclk(_hw) container_of(_hw, struct clk_std, hw) - -static int std_clk_is_enabled(struct clk_hw *hw) -{ - struct clk_std *std = to_stdclk(hw); - - return readl_relaxed(SYSCTRL_CLK_STAT) & BIT(std->bit); -} - -static int std_clk_enable(struct clk_hw *hw) -{ - struct clk_std *std = to_stdclk(hw); - - writel(BIT(std->bit), SYS_CTRL_CLK_SET_CTRL); - return 0; -} - -static void std_clk_disable(struct clk_hw *hw) -{ - struct clk_std *std = to_stdclk(hw); - - writel(BIT(std->bit), SYS_CTRL_CLK_CLR_CTRL); -} - -static struct clk_ops std_clk_ops = { - .enable = std_clk_enable, - .disable = std_clk_disable, - .is_enabled = std_clk_is_enabled, -}; - -static const char *std_clk_parents[] = { - "oscillator", -}; - -static const char *eth_parents[] = { - "gmacclk", -}; - -#define DECLARE_STD_CLKP(__clk, __bit, __parent) \ -static struct clk_init_data clk_##__clk##_init = { \ - .name = __stringify(__clk), \ - .ops = &std_clk_ops, \ - .parent_names = __parent, \ - .num_parents = ARRAY_SIZE(__parent), \ -}; \ - \ -static struct clk_std clk_##__clk = { \ - .bit = __bit, \ - .hw = { \ - .init = &clk_##__clk##_init, \ - }, \ -} - -#define DECLARE_STD_CLK(__clk, __bit) DECLARE_STD_CLKP(__clk, __bit, \ - std_clk_parents) - -DECLARE_STD_CLK(leon, 0); -DECLARE_STD_CLK(dma_sgdma, 1); -DECLARE_STD_CLK(cipher, 2); -DECLARE_STD_CLK(sd, 3); -DECLARE_STD_CLK(sata, 4); -DECLARE_STD_CLK(audio, 5); -DECLARE_STD_CLK(usbmph, 6); -DECLARE_STD_CLKP(etha, 7, eth_parents); -DECLARE_STD_CLK(pciea, 8); -DECLARE_STD_CLK(static, 9); -DECLARE_STD_CLK(ethb, 10); -DECLARE_STD_CLK(pcieb, 11); -DECLARE_STD_CLK(ref600, 12); -DECLARE_STD_CLK(usbdev, 13); - -struct clk_hw *std_clk_hw_tbl[] = { - &clk_leon.hw, - &clk_dma_sgdma.hw, - &clk_cipher.hw, - &clk_sd.hw, - &clk_sata.hw, - &clk_audio.hw, - &clk_usbmph.hw, - &clk_etha.hw, - &clk_pciea.hw, - &clk_static.hw, - &clk_ethb.hw, - &clk_pcieb.hw, - &clk_ref600.hw, - &clk_usbdev.hw, -}; - -struct clk *std_clk_tbl[ARRAY_SIZE(std_clk_hw_tbl)]; - -static struct clk_onecell_data std_clk_data; - -void __init oxnas_init_stdclk(struct device_node *np) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(std_clk_hw_tbl); i++) { - std_clk_tbl[i] = clk_register(NULL, std_clk_hw_tbl[i]); - BUG_ON(IS_ERR(std_clk_tbl[i])); - } - std_clk_data.clks = std_clk_tbl; - std_clk_data.clk_num = ARRAY_SIZE(std_clk_tbl); - of_clk_add_provider(np, of_clk_src_onecell_get, &std_clk_data); -} -CLK_OF_DECLARE(oxnas_pllstd, "plxtech,nas782x-stdclk", oxnas_init_stdclk); - -void __init oxnas_init_plla(struct device_node *np) -{ - struct clk *clk; - - clk = clk_register(NULL, &plla_hw); - BUG_ON(IS_ERR(clk)); - /* mark it as enabled */ - clk_prepare_enable(clk); - of_clk_add_provider(np, of_clk_src_simple_get, clk); -} -CLK_OF_DECLARE(oxnas_plla, "plxtech,nas782x-plla", oxnas_init_plla); - -void __init oxnas_init_pllb(struct device_node *np) -{ - struct clk *clk; - struct clk_oxnas_pllb *pllb; - - pllb = kmalloc(sizeof(*pllb), GFP_KERNEL); - BUG_ON(!pllb); - - pllb->hw.init = &clk_pllb_init; - pllb->devnode = np; - pllb->rstc = NULL; - - clk = clk_register(NULL, &pllb->hw); - BUG_ON(IS_ERR(clk)); - of_clk_add_provider(np, of_clk_src_simple_get, clk); -} -CLK_OF_DECLARE(oxnas_pllb, "plxtech,nas782x-pllb", oxnas_init_pllb); diff --git a/target/linux/oxnas/files/drivers/clocksource/oxnas_rps_timer.c b/target/linux/oxnas/files/drivers/clocksource/oxnas_rps_timer.c deleted file mode 100644 index 7c8c4cf435..0000000000 --- a/target/linux/oxnas/files/drivers/clocksource/oxnas_rps_timer.c +++ /dev/null @@ -1,96 +0,0 @@ -/* - * arch/arm/mach-ox820/rps-time.c - * - * Copyright (C) 2009 Oxford Semiconductor Ltd - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#include <linux/init.h> -#include <linux/interrupt.h> -#include <linux/irq.h> -#include <linux/io.h> -#include <linux/clockchips.h> -#include <linux/clk.h> -#include <linux/of_irq.h> -#include <linux/of_address.h> -#include <linux/sched_clock.h> -#include <mach/hardware.h> - -enum { - TIMER_LOAD = 0, - TIMER_CURR = 4, - TIMER_CTRL = 8, - TIMER_CLRINT = 0xC, - - TIMER_BITS = 24, - - TIMER_MAX_VAL = (1 << TIMER_BITS) - 1, - - TIMER_PERIODIC = (1 << 6), - TIMER_ENABLE = (1 << 7), - - TIMER_DIV1 = (0 << 2), - TIMER_DIV16 = (1 << 2), - TIMER_DIV256 = (2 << 2), - - TIMER1_OFFSET = 0, - TIMER2_OFFSET = 0x20, - -}; - -static u64 notrace rps_read_sched_clock(void) -{ - return ~readl_relaxed(RPSA_TIMER2_VAL); -} - -static void __init rps_clocksource_init(void __iomem *base, ulong ref_rate) -{ - int ret; - ulong clock_rate; - /* use prescale 16 */ - clock_rate = ref_rate / 16; - - iowrite32(TIMER_MAX_VAL, base + TIMER_LOAD); - iowrite32(TIMER_PERIODIC | TIMER_ENABLE | TIMER_DIV16, - base + TIMER_CTRL); - - ret = clocksource_mmio_init(base + TIMER_CURR, "rps_clocksource_timer", - clock_rate, 250, TIMER_BITS, - clocksource_mmio_readl_down); - if (ret) - panic("can't register clocksource\n"); - - sched_clock_register(rps_read_sched_clock, TIMER_BITS, clock_rate); -} - -static void __init rps_timer_init(struct device_node *np) -{ - struct clk *refclk; - unsigned long ref_rate; - void __iomem *base; - - refclk = of_clk_get(np, 0); - - if (IS_ERR(refclk) || clk_prepare_enable(refclk)) - panic("rps_timer_init: failed to get refclk\n"); - ref_rate = clk_get_rate(refclk); - - base = of_iomap(np, 0); - if (!base) - panic("rps_timer_init: failed to map io\n"); - - rps_clocksource_init(base + TIMER2_OFFSET, ref_rate); -} - -CLOCKSOURCE_OF_DECLARE(nas782x, "plxtech,nas782x-rps-timer", rps_timer_init); diff --git a/target/linux/oxnas/files/drivers/irqchip/irq-rps.c b/target/linux/oxnas/files/drivers/irqchip/irq-rps.c deleted file mode 100644 index f2b0829de6..0000000000 --- a/target/linux/oxnas/files/drivers/irqchip/irq-rps.c +++ /dev/null @@ -1,145 +0,0 @@ -#include <linux/irqdomain.h> -#include <linux/irq.h> -#include <linux/of.h> -#include <linux/of_address.h> -#include <linux/of_irq.h> -#include <linux/irqchip/chained_irq.h> -#include <linux/err.h> -#include <linux/io.h> -#include <linux/irqchip.h> - -struct rps_chip_data { - void __iomem *base; - struct irq_chip chip; - struct irq_domain *domain; -} rps_data; - -enum { - RPS_IRQ_BASE = 64, - RPS_IRQ_COUNT = 32, - PRS_HWIRQ_BASE = 0, - - RPS_STATUS = 0, - RPS_RAW_STATUS = 4, - RPS_UNMASK = 8, - RPS_MASK = 0xc, -}; - -/* - * Routines to acknowledge, disable and enable interrupts - */ -static void rps_mask_irq(struct irq_data *d) -{ - struct rps_chip_data *chip_data = irq_data_get_irq_chip_data(d); - u32 mask = BIT(d->hwirq); - - iowrite32(mask, chip_data->base + RPS_MASK); -} - -static void rps_unmask_irq(struct irq_data *d) -{ - struct rps_chip_data *chip_data = irq_data_get_irq_chip_data(d); - u32 mask = BIT(d->hwirq); - - iowrite32(mask, chip_data->base + RPS_UNMASK); -} - -static struct irq_chip rps_chip = { - .name = "RPS", - .irq_mask = rps_mask_irq, - .irq_unmask = rps_unmask_irq, -}; - -static int rps_irq_domain_xlate(struct irq_domain *d, - struct device_node *controller, - const u32 *intspec, unsigned int intsize, - unsigned long *out_hwirq, - unsigned int *out_type) -{ - if (irq_domain_get_of_node(d) != controller) - return -EINVAL; - if (intsize < 1) - return -EINVAL; - - *out_hwirq = intspec[0]; - /* Honestly I do not know the type */ - *out_type = IRQ_TYPE_LEVEL_HIGH; - - return 0; -} - -static int rps_irq_domain_map(struct irq_domain *d, unsigned int irq, - irq_hw_number_t hw) -{ - irq_set_chip_and_handler(irq, &rps_chip, handle_level_irq); - irq_set_probe(irq); - irq_set_chip_data(irq, d->host_data); - return 0; -} - -const struct irq_domain_ops rps_irq_domain_ops = { - .map = rps_irq_domain_map, - .xlate = rps_irq_domain_xlate, -}; - -static void rps_handle_cascade_irq(struct irq_desc *desc) -{ - struct rps_chip_data *chip_data = irq_desc_get_handler_data(desc); - struct irq_chip *chip = irq_desc_get_chip(desc); - unsigned int cascade_irq, rps_irq; - u32 status; - - chained_irq_enter(chip, desc); - - status = ioread32(chip_data->base + RPS_STATUS); - rps_irq = __ffs(status); - cascade_irq = irq_find_mapping(chip_data->domain, rps_irq); - - if (unlikely(rps_irq >= RPS_IRQ_COUNT)) - handle_bad_irq(desc); - else - generic_handle_irq(cascade_irq); - - chained_irq_exit(chip, desc); -} - -#ifdef CONFIG_OF -int __init rps_of_init(struct device_node *node, struct device_node *parent) -{ - void __iomem *rps_base; - int irq_start = RPS_IRQ_BASE; - int irq_base; - int irq; - - if (WARN_ON(!node)) - return -ENODEV; - - rps_base = of_iomap(node, 0); - WARN(!rps_base, "unable to map rps registers\n"); - rps_data.base = rps_base; - - irq_base = irq_alloc_descs(irq_start, 0, RPS_IRQ_COUNT, numa_node_id()); - if (IS_ERR_VALUE(irq_base)) { - WARN(1, "Cannot allocate irq_descs @ IRQ%d, assuming pre-allocated\n", - irq_start); - irq_base = irq_start; - } - - rps_data.domain = irq_domain_add_legacy(node, RPS_IRQ_COUNT, irq_base, - PRS_HWIRQ_BASE, &rps_irq_domain_ops, &rps_data); - - if (WARN_ON(!rps_data.domain)) - return -ENOMEM; - - if (parent) { - irq = irq_of_parse_and_map(node, 0); - if (irq_set_handler_data(irq, &rps_data) != 0) - BUG(); - irq_set_chained_handler(irq, rps_handle_cascade_irq); - } - return 0; - -} - -IRQCHIP_DECLARE(nas782x, "plxtech,nas782x-rps", rps_of_init); -#endif diff --git a/target/linux/oxnas/files/drivers/mtd/nand/oxnas_nand.c b/target/linux/oxnas/files/drivers/mtd/nand/oxnas_nand.c deleted file mode 100644 index 36807b7767..0000000000 --- a/target/linux/oxnas/files/drivers/mtd/nand/oxnas_nand.c +++ /dev/null @@ -1,206 +0,0 @@ -/* - * Oxford Semiconductor OXNAS NAND driver - - * Copyright (C) 2016 Neil Armstrong <narmstrong@baylibre.com> - * Heavily based on plat_nand.c : - * Author: Vitaly Wool <vitalywool@gmail.com> - * Copyright (C) 2013 Ma Haijun <mahaijuns@gmail.com> - * Copyright (C) 2012 John Crispin <blogic@openwrt.org> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - */ - -#include <linux/err.h> -#include <linux/io.h> -#include <linux/module.h> -#include <linux/platform_device.h> -#include <linux/slab.h> -#include <linux/clk.h> -#include <linux/reset.h> -#include <linux/mtd/mtd.h> -#include <linux/mtd/nand.h> -#include <linux/mtd/partitions.h> -#include <linux/of.h> - -/* Nand commands */ -#define OXNAS_NAND_CMD_ALE BIT(18) -#define OXNAS_NAND_CMD_CLE BIT(19) - -#define OXNAS_NAND_MAX_CHIPS 1 - -struct oxnas_nand { - struct nand_hw_control base; - void __iomem *io_base; - struct clk *clk; - struct nand_chip *chips[OXNAS_NAND_MAX_CHIPS]; - unsigned long ctrl; - struct mtd_partition *partitions; - int nr_partitions; -}; - -static uint8_t oxnas_nand_read_byte(struct mtd_info *mtd) -{ - struct nand_chip *chip = mtd_to_nand(mtd); - struct oxnas_nand *oxnas = nand_get_controller_data(chip); - - return readb(oxnas->io_base); -} - -static void oxnas_nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len) -{ - struct nand_chip *chip = mtd_to_nand(mtd); - struct oxnas_nand *oxnas = nand_get_controller_data(chip); - - ioread8_rep(oxnas->io_base, buf, len); -} - -static void oxnas_nand_write_buf(struct mtd_info *mtd, - const uint8_t *buf, int len) -{ - struct nand_chip *chip = mtd_to_nand(mtd); - struct oxnas_nand *oxnas = nand_get_controller_data(chip); - - iowrite8_rep(oxnas->io_base + oxnas->ctrl, buf, len); -} - -/* Single CS command control */ -static void oxnas_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, - unsigned int ctrl) -{ - struct nand_chip *chip = mtd_to_nand(mtd); - struct oxnas_nand *oxnas = nand_get_controller_data(chip); - - if (ctrl & NAND_CTRL_CHANGE) { - if (ctrl & NAND_CLE) - oxnas->ctrl = OXNAS_NAND_CMD_CLE; - else if (ctrl & NAND_ALE) - oxnas->ctrl = OXNAS_NAND_CMD_ALE; - else - oxnas->ctrl = 0; - } - - if (cmd != NAND_CMD_NONE) - writeb(cmd, oxnas->io_base + oxnas->ctrl); -} - -/* - * Probe for the NAND device. - */ -static int oxnas_nand_probe(struct platform_device *pdev) -{ - struct device_node *np = pdev->dev.of_node; - struct device_node *nand_np; - struct oxnas_nand *oxnas; - struct nand_chip *chip; - struct mtd_info *mtd; - struct resource *res; - int nchips = 0; - int count = 0; - int err = 0; - - /* Allocate memory for the device structure (and zero it) */ - oxnas = devm_kzalloc(&pdev->dev, sizeof(struct nand_chip), - GFP_KERNEL); - if (!oxnas) - return -ENOMEM; - - nand_hw_control_init(&oxnas->base); - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - oxnas->io_base = devm_ioremap_resource(&pdev->dev, res); - if (IS_ERR(oxnas->io_base)) - return PTR_ERR(oxnas->io_base); - - oxnas->clk = devm_clk_get(&pdev->dev, NULL); - if (IS_ERR(oxnas->clk)) - oxnas->clk = NULL; - - /* Only a single chip node is supported */ - count = of_get_child_count(np); - if (count > 1) - return -EINVAL; - - clk_prepare_enable(oxnas->clk); - device_reset_optional(&pdev->dev); - - for_each_child_of_node(np, nand_np) { - chip = devm_kzalloc(&pdev->dev, sizeof(struct nand_chip), - GFP_KERNEL); - if (!chip) - return -ENOMEM; - - chip->controller = &oxnas->base; - - nand_set_flash_node(chip, nand_np); - nand_set_controller_data(chip, oxnas); - - mtd = nand_to_mtd(chip); - mtd->dev.parent = &pdev->dev; - mtd->priv = chip; - - chip->cmd_ctrl = oxnas_nand_cmd_ctrl; - chip->read_buf = oxnas_nand_read_buf; - chip->read_byte = oxnas_nand_read_byte; - chip->write_buf = oxnas_nand_write_buf; - chip->chip_delay = 30; - - /* Scan to find existence of the device */ - err = nand_scan(mtd, 1); - if (err) - return err; - - err = mtd_device_register(mtd, NULL, 0); - if (err) { - nand_release(mtd); - return err; - } - - oxnas->chips[nchips] = chip; - ++nchips; - } - - /* Exit if no chips found */ - if (!nchips) - return -ENODEV; - - platform_set_drvdata(pdev, oxnas); - - return 0; -} - -static int oxnas_nand_remove(struct platform_device *pdev) -{ - struct oxnas_nand *oxnas = platform_get_drvdata(pdev); - - if (oxnas->chips[0]) - nand_release(nand_to_mtd(oxnas->chips[0])); - - clk_disable_unprepare(oxnas->clk); - - return 0; -} - -static const struct of_device_id oxnas_nand_match[] = { - { .compatible = "oxsemi,ox820-nand" }, - {}, -}; -MODULE_DEVICE_TABLE(of, oxnas_nand_match); - -static struct platform_driver oxnas_nand_driver = { - .probe = oxnas_nand_probe, - .remove = oxnas_nand_remove, - .driver = { - .name = "oxnas_nand", - .of_match_table = oxnas_nand_match, - }, -}; - -module_platform_driver(oxnas_nand_driver); - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Neil Armstrong <narmstrong@baylibre.com>"); -MODULE_DESCRIPTION("Oxnas NAND driver"); -MODULE_ALIAS("platform:oxnas_nand"); diff --git a/target/linux/oxnas/files/drivers/net/ethernet/stmicro/stmmac/dwmac-oxnas.c b/target/linux/oxnas/files/drivers/net/ethernet/stmicro/stmmac/dwmac-oxnas.c deleted file mode 100644 index aafb118144..0000000000 --- a/target/linux/oxnas/files/drivers/net/ethernet/stmicro/stmmac/dwmac-oxnas.c +++ /dev/null @@ -1,145 +0,0 @@ -/* Copyright OpenWrt.org (C) 2015. - * Copyright Altera Corporation (C) 2014. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License, version 2, - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * - * Adopted from dwmac-socfpga.c - * Based on code found in mach-oxnas.c - */ - -#include <linux/mfd/syscon.h> -#include <linux/of.h> -#include <linux/of_address.h> -#include <linux/of_net.h> -#include <linux/phy.h> -#include <linux/regmap.h> -#include <linux/reset.h> -#include <linux/stmmac.h> - -#include <mach/hardware.h> - -#include "stmmac.h" -#include "stmmac_platform.h" - -struct oxnas_gmac { - struct clk *clk; -}; - -static int oxnas_gmac_init(struct platform_device *pdev, void *priv) -{ - struct oxnas_gmac *bsp_priv = priv; - int ret = 0; - unsigned value; - - ret = device_reset(&pdev->dev); - if (ret) - return ret; - - if (IS_ERR(bsp_priv->clk)) - return PTR_ERR(bsp_priv->clk); - clk_prepare_enable(bsp_priv->clk); - - value = readl(SYS_CTRL_GMAC_CTRL); - - /* Enable GMII_GTXCLK to follow GMII_REFCLK, required for gigabit PHY */ - value |= BIT(SYS_CTRL_GMAC_CKEN_GTX); - /* Use simple mux for 25/125 Mhz clock switching */ - value |= BIT(SYS_CTRL_GMAC_SIMPLE_MUX); - /* set auto switch tx clock source */ - value |= BIT(SYS_CTRL_GMAC_AUTO_TX_SOURCE); - /* enable tx & rx vardelay */ - value |= BIT(SYS_CTRL_GMAC_CKEN_TX_OUT); - value |= BIT(SYS_CTRL_GMAC_CKEN_TXN_OUT); - value |= BIT(SYS_CTRL_GMAC_CKEN_TX_IN); - value |= BIT(SYS_CTRL_GMAC_CKEN_RX_OUT); - value |= BIT(SYS_CTRL_GMAC_CKEN_RXN_OUT); - value |= BIT(SYS_CTRL_GMAC_CKEN_RX_IN); - writel(value, SYS_CTRL_GMAC_CTRL); - - /* set tx & rx vardelay */ - value = 0; - value |= SYS_CTRL_GMAC_TX_VARDELAY(4); - value |= SYS_CTRL_GMAC_TXN_VARDELAY(2); - value |= SYS_CTRL_GMAC_RX_VARDELAY(10); - value |= SYS_CTRL_GMAC_RXN_VARDELAY(8); - writel(value, SYS_CTRL_GMAC_DELAY_CTRL); - - return 0; -} - -static void oxnas_gmac_exit(struct platform_device *pdev, void *priv) -{ - struct reset_control *rstc; - - clk_disable_unprepare(priv); - devm_clk_put(&pdev->dev, priv); - - rstc = reset_control_get(&pdev->dev, NULL); - if (!IS_ERR(rstc)) { - reset_control_assert(rstc); - reset_control_put(rstc); - } -} - -static int oxnas_gmac_probe(struct platform_device *pdev) -{ - struct plat_stmmacenet_data *plat_dat; - struct stmmac_resources stmmac_res; - int ret; - struct device *dev = &pdev->dev; - struct oxnas_gmac *bsp_priv; - - bsp_priv = devm_kzalloc(dev, sizeof(*bsp_priv), GFP_KERNEL); - if (!bsp_priv) - return -ENOMEM; - bsp_priv->clk = devm_clk_get(dev, "gmac"); - if (IS_ERR(bsp_priv->clk)) - return PTR_ERR(bsp_priv->clk); - - ret = stmmac_get_platform_resources(pdev, &stmmac_res); - if (ret) - return ret; - - plat_dat = stmmac_probe_config_dt(pdev, &stmmac_res.mac); - if (IS_ERR(plat_dat)) - return PTR_ERR(plat_dat); - - plat_dat->bsp_priv = bsp_priv; - plat_dat->init = oxnas_gmac_init; - plat_dat->exit = oxnas_gmac_exit; - - ret = oxnas_gmac_init(pdev, bsp_priv); - if (ret) - return ret; - - return stmmac_dvr_probe(dev, plat_dat, &stmmac_res); -} - -static const struct of_device_id oxnas_gmac_match[] = { - { .compatible = "plxtech,nas782x-gmac" }, - { } -}; -MODULE_DEVICE_TABLE(of, oxnas_gmac_match); - -static struct platform_driver oxnas_gmac_driver = { - .probe = oxnas_gmac_probe, - .remove = stmmac_pltfr_remove, - .driver = { - .name = "oxnas-gmac", - .pm = &stmmac_pltfr_pm_ops, - .of_match_table = oxnas_gmac_match, - }, -}; -module_platform_driver(oxnas_gmac_driver); - -MODULE_LICENSE("GPL v2"); diff --git a/target/linux/oxnas/files/drivers/pci/host/pcie-oxnas.c b/target/linux/oxnas/files/drivers/pci/host/pcie-oxnas.c index 9e8d6d9f93..7cf3ad1670 100644 --- a/target/linux/oxnas/files/drivers/pci/host/pcie-oxnas.c +++ b/target/linux/oxnas/files/drivers/pci/host/pcie-oxnas.c @@ -22,9 +22,279 @@ #include <linux/delay.h> #include <linux/clk.h> #include <linux/reset.h> -#include <mach/iomap.h> -#include <mach/hardware.h> -#include <mach/utils.h> +#include <linux/io.h> +#include <linux/sizes.h> + +#define OXNAS_UART1_BASE 0x44200000 +#define OXNAS_UART1_SIZE SZ_32 +#define OXNAS_UART1_BASE_VA 0xF0000000 + +#define OXNAS_UART2_BASE 0x44300000 +#define OXNAS_UART2_SIZE SZ_32 + +#define OXNAS_PERCPU_BASE 0x47000000 +#define OXNAS_PERCPU_SIZE SZ_8K +#define OXNAS_PERCPU_BASE_VA 0xF0002000 + +#define OXNAS_SYSCRTL_BASE 0x44E00000 +#define OXNAS_SYSCRTL_SIZE SZ_4K +#define OXNAS_SYSCRTL_BASE_VA 0xF0004000 + +#define OXNAS_SECCRTL_BASE 0x44F00000 +#define OXNAS_SECCRTL_SIZE SZ_4K +#define OXNAS_SECCRTL_BASE_VA 0xF0005000 + +#define OXNAS_RPSA_BASE 0x44400000 +#define OXNAS_RPSA_SIZE SZ_4K +#define OXNAS_RPSA_BASE_VA 0xF0006000 + +#define OXNAS_RPSC_BASE 0x44500000 +#define OXNAS_RPSC_SIZE SZ_4K +#define OXNAS_RPSC_BASE_VA 0xF0007000 + + +/* + * Location of flags and vectors in SRAM for controlling the booting of the + * secondary ARM11 processors. + */ + +#define OXNAS_SCU_BASE_VA OXNAS_PERCPU_BASE_VA +#define OXNAS_GICN_BASE_VA(n) (OXNAS_PERCPU_BASE_VA + 0x200 + n*0x100) + +#define HOLDINGPEN_CPU IOMEM(OXNAS_SYSCRTL_BASE_VA + 0xc8) +#define HOLDINGPEN_LOCATION IOMEM(OXNAS_SYSCRTL_BASE_VA + 0xc4) + +/** + * System block reset and clock control + */ +#define SYS_CTRL_PCI_STAT IOMEM(OXNAS_SYSCRTL_BASE_VA + 0x20) +#define SYSCTRL_CLK_STAT IOMEM(OXNAS_SYSCRTL_BASE_VA + 0x24) +#define SYS_CTRL_CLK_SET_CTRL IOMEM(OXNAS_SYSCRTL_BASE_VA + 0x2C) +#define SYS_CTRL_CLK_CLR_CTRL IOMEM(OXNAS_SYSCRTL_BASE_VA + 0x30) +#define SYS_CTRL_RST_SET_CTRL IOMEM(OXNAS_SYSCRTL_BASE_VA + 0x34) +#define SYS_CTRL_RST_CLR_CTRL IOMEM(OXNAS_SYSCRTL_BASE_VA + 0x38) + +#define SYS_CTRL_PLLSYS_CTRL IOMEM(OXNAS_SYSCRTL_BASE_VA + 0x48) +#define SYS_CTRL_CLK_CTRL IOMEM(OXNAS_SYSCRTL_BASE_VA + 0x64) +#define SYS_CTRL_PLLSYS_KEY_CTRL IOMEM(OXNAS_SYSCRTL_BASE_VA + 0x6C) +#define SYS_CTRL_GMAC_CTRL IOMEM(OXNAS_SYSCRTL_BASE_VA + 0x78) +#define SYS_CTRL_GMAC_DELAY_CTRL IOMEM(OXNAS_SYSCRTL_BASE_VA + 0x100) + +/* Scratch registers */ +#define SYS_CTRL_SCRATCHWORD0 IOMEM(OXNAS_SYSCRTL_BASE_VA + 0xc4) +#define SYS_CTRL_SCRATCHWORD1 IOMEM(OXNAS_SYSCRTL_BASE_VA + 0xc8) +#define SYS_CTRL_SCRATCHWORD2 IOMEM(OXNAS_SYSCRTL_BASE_VA + 0xcc) +#define SYS_CTRL_SCRATCHWORD3 IOMEM(OXNAS_SYSCRTL_BASE_VA + 0xd0) + +#define SYS_CTRL_PLLA_CTRL0 IOMEM(OXNAS_SYSCRTL_BASE_VA + 0x1F0) +#define SYS_CTRL_PLLA_CTRL1 IOMEM(OXNAS_SYSCRTL_BASE_VA + 0x1F4) +#define SYS_CTRL_PLLA_CTRL2 IOMEM(OXNAS_SYSCRTL_BASE_VA + 0x1F8) +#define SYS_CTRL_PLLA_CTRL3 IOMEM(OXNAS_SYSCRTL_BASE_VA + 0x1FC) + +#define SYS_CTRL_USBHSMPH_CTRL IOMEM(OXNAS_SYSCRTL_BASE_VA + 0x40) +#define SYS_CTRL_USBHSMPH_STAT IOMEM(OXNAS_SYSCRTL_BASE_VA + 0x44) +#define SYS_CTRL_REF300_DIV IOMEM(OXNAS_SYSCRTL_BASE_VA + 0xF8) +#define SYS_CTRL_USBHSPHY_CTRL IOMEM(OXNAS_SYSCRTL_BASE_VA + 0x84) +#define SYS_CTRL_USB_CTRL IOMEM(OXNAS_SYSCRTL_BASE_VA + 0x90) + +/* pcie */ +#define SYS_CTRL_HCSL_CTRL IOMEM(OXNAS_SYSCRTL_BASE_VA + 0x114) + +/* System control multi-function pin function selection */ +#define SYS_CTRL_SECONDARY_SEL IOMEM(OXNAS_SYSCRTL_BASE_VA + 0x14) +#define SYS_CTRL_TERTIARY_SEL IOMEM(OXNAS_SYSCRTL_BASE_VA + 0x8c) +#define SYS_CTRL_QUATERNARY_SEL IOMEM(OXNAS_SYSCRTL_BASE_VA + 0x94) +#define SYS_CTRL_DEBUG_SEL IOMEM(OXNAS_SYSCRTL_BASE_VA + 0x9c) +#define SYS_CTRL_ALTERNATIVE_SEL IOMEM(OXNAS_SYSCRTL_BASE_VA + 0xa4) +#define SYS_CTRL_PULLUP_SEL IOMEM(OXNAS_SYSCRTL_BASE_VA + 0xac) + +/* Secure control multi-function pin function selection */ +#define SEC_CTRL_SECONDARY_SEL IOMEM(OXNAS_SECCRTL_BASE_VA + 0x14) +#define SEC_CTRL_TERTIARY_SEL IOMEM(OXNAS_SECCRTL_BASE_VA + 0x8c) +#define SEC_CTRL_QUATERNARY_SEL IOMEM(OXNAS_SECCRTL_BASE_VA + 0x94) +#define SEC_CTRL_DEBUG_SEL IOMEM(OXNAS_SECCRTL_BASE_VA + 0x9c) +#define SEC_CTRL_ALTERNATIVE_SEL IOMEM(OXNAS_SECCRTL_BASE_VA + 0xa4) +#define SEC_CTRL_PULLUP_SEL IOMEM(OXNAS_SECCRTL_BASE_VA + 0xac) + +#define SEC_CTRL_COPRO_CTRL IOMEM(OXNAS_SECCRTL_BASE_VA + 0x68) +#define SEC_CTRL_SECURE_CTRL IOMEM(OXNAS_SECCRTL_BASE_VA + 0x98) +#define SEC_CTRL_LEON_DEBUG IOMEM(OXNAS_SECCRTL_BASE_VA + 0xF0) +#define SEC_CTRL_PLLB_DIV_CTRL IOMEM(OXNAS_SECCRTL_BASE_VA + 0xF8) +#define SEC_CTRL_PLLB_CTRL0 IOMEM(OXNAS_SECCRTL_BASE_VA + 0x1F0) +#define SEC_CTRL_PLLB_CTRL1 IOMEM(OXNAS_SECCRTL_BASE_VA + 0x1F4) +#define SEC_CTRL_PLLB_CTRL8 IOMEM(OXNAS_SECCRTL_BASE_VA + 0x1F4) + +#define RPSA_IRQ_SOFT IOMEM(OXNAS_RPSA_BASE_VA + 0x10) +#define RPSA_FIQ_ENABLE IOMEM(OXNAS_RPSA_BASE_VA + 0x108) +#define RPSA_FIQ_DISABLE IOMEM(OXNAS_RPSA_BASE_VA + 0x10C) +#define RPSA_FIQ_IRQ_TO_FIQ IOMEM(OXNAS_RPSA_BASE_VA + 0x1FC) + +#define RPSC_IRQ_SOFT IOMEM(OXNAS_RPSC_BASE_VA + 0x10) +#define RPSC_FIQ_ENABLE IOMEM(OXNAS_RPSC_BASE_VA + 0x108) +#define RPSC_FIQ_DISABLE IOMEM(OXNAS_RPSC_BASE_VA + 0x10C) +#define RPSC_FIQ_IRQ_TO_FIQ IOMEM(OXNAS_RPSC_BASE_VA + 0x1FC) + +#define RPSA_TIMER2_VAL IOMEM(OXNAS_RPSA_BASE_VA + 0x224) + +#define REF300_DIV_INT_SHIFT 8 +#define REF300_DIV_FRAC_SHIFT 0 +#define REF300_DIV_INT(val) ((val) << REF300_DIV_INT_SHIFT) +#define REF300_DIV_FRAC(val) ((val) << REF300_DIV_FRAC_SHIFT) + +#define USBHSPHY_SUSPENDM_MANUAL_ENABLE 16 +#define USBHSPHY_SUSPENDM_MANUAL_STATE 15 +#define USBHSPHY_ATE_ESET 14 +#define USBHSPHY_TEST_DIN 6 +#define USBHSPHY_TEST_ADD 2 +#define USBHSPHY_TEST_DOUT_SEL 1 +#define USBHSPHY_TEST_CLK 0 + +#define USB_CTRL_USBAPHY_CKSEL_SHIFT 5 +#define USB_CLK_XTAL0_XTAL1 (0 << USB_CTRL_USBAPHY_CKSEL_SHIFT) +#define USB_CLK_XTAL0 (1 << USB_CTRL_USBAPHY_CKSEL_SHIFT) +#define USB_CLK_INTERNAL (2 << USB_CTRL_USBAPHY_CKSEL_SHIFT) + +#define USBAMUX_DEVICE BIT(4) + +#define USBPHY_REFCLKDIV_SHIFT 2 +#define USB_PHY_REF_12MHZ (0 << USBPHY_REFCLKDIV_SHIFT) +#define USB_PHY_REF_24MHZ (1 << USBPHY_REFCLKDIV_SHIFT) +#define USB_PHY_REF_48MHZ (2 << USBPHY_REFCLKDIV_SHIFT) + +#define USB_CTRL_USB_CKO_SEL_BIT 0 + +#define USB_INT_CLK_XTAL 0 +#define USB_INT_CLK_REF300 2 +#define USB_INT_CLK_PLLB 3 + +#define SYS_CTRL_GMAC_CKEN_RX_IN 14 +#define SYS_CTRL_GMAC_CKEN_RXN_OUT 13 +#define SYS_CTRL_GMAC_CKEN_RX_OUT 12 +#define SYS_CTRL_GMAC_CKEN_TX_IN 10 +#define SYS_CTRL_GMAC_CKEN_TXN_OUT 9 +#define SYS_CTRL_GMAC_CKEN_TX_OUT 8 +#define SYS_CTRL_GMAC_RX_SOURCE 7 +#define SYS_CTRL_GMAC_TX_SOURCE 6 +#define SYS_CTRL_GMAC_LOW_TX_SOURCE 4 +#define SYS_CTRL_GMAC_AUTO_TX_SOURCE 3 +#define SYS_CTRL_GMAC_RGMII 2 +#define SYS_CTRL_GMAC_SIMPLE_MUX 1 +#define SYS_CTRL_GMAC_CKEN_GTX 0 +#define SYS_CTRL_GMAC_TX_VARDELAY_SHIFT 0 +#define SYS_CTRL_GMAC_TXN_VARDELAY_SHIFT 8 +#define SYS_CTRL_GMAC_RX_VARDELAY_SHIFT 16 +#define SYS_CTRL_GMAC_RXN_VARDELAY_SHIFT 24 +#define SYS_CTRL_GMAC_TX_VARDELAY(d) ((d)<<SYS_CTRL_GMAC_TX_VARDELAY_SHIFT) +#define SYS_CTRL_GMAC_TXN_VARDELAY(d) ((d)<<SYS_CTRL_GMAC_TXN_VARDELAY_SHIFT) +#define SYS_CTRL_GMAC_RX_VARDELAY(d) ((d)<<SYS_CTRL_GMAC_RX_VARDELAY_SHIFT) +#define SYS_CTRL_GMAC_RXN_VARDELAY(d) ((d)<<SYS_CTRL_GMAC_RXN_VARDELAY_SHIFT) + +#define PLLB_BYPASS 1 +#define PLLB_ENSAT 3 +#define PLLB_OUTDIV 4 +#define PLLB_REFDIV 8 +#define PLLB_DIV_INT_SHIFT 8 +#define PLLB_DIV_FRAC_SHIFT 0 +#define PLLB_DIV_INT(val) ((val) << PLLB_DIV_INT_SHIFT) +#define PLLB_DIV_FRAC(val) ((val) << PLLB_DIV_FRAC_SHIFT) + +#define SYS_CTRL_CKCTRL_PCI_DIV_BIT 0 +#define SYS_CTRL_CKCTRL_SLOW_BIT 8 + +#define SYS_CTRL_UART2_DEQ_EN 0 +#define SYS_CTRL_UART3_DEQ_EN 1 +#define SYS_CTRL_UART3_IQ_EN 2 +#define SYS_CTRL_UART4_IQ_EN 3 +#define SYS_CTRL_UART4_NOT_PCI_MODE 4 + +#define SYS_CTRL_PCI_CTRL1_PCI_STATIC_RQ_BIT 11 + +#define PLLA_REFDIV_MASK 0x3F +#define PLLA_REFDIV_SHIFT 8 +#define PLLA_OUTDIV_MASK 0x7 +#define PLLA_OUTDIV_SHIFT 4 + +/* bit numbers of clock control register */ +#define SYS_CTRL_CLK_COPRO 0 +#define SYS_CTRL_CLK_DMA 1 +#define SYS_CTRL_CLK_CIPHER 2 +#define SYS_CTRL_CLK_SD 3 +#define SYS_CTRL_CLK_SATA 4 +#define SYS_CTRL_CLK_I2S 5 +#define SYS_CTRL_CLK_USBHS 6 +#define SYS_CTRL_CLK_MACA 7 +#define SYS_CTRL_CLK_MAC SYS_CTRL_CLK_MACA +#define SYS_CTRL_CLK_PCIEA 8 +#define SYS_CTRL_CLK_STATIC 9 +#define SYS_CTRL_CLK_MACB 10 +#define SYS_CTRL_CLK_PCIEB 11 +#define SYS_CTRL_CLK_REF600 12 +#define SYS_CTRL_CLK_USBDEV 13 +#define SYS_CTRL_CLK_DDR 14 +#define SYS_CTRL_CLK_DDRPHY 15 +#define SYS_CTRL_CLK_DDRCK 16 + + +/* bit numbers of reset control register */ +#define SYS_CTRL_RST_SCU 0 +#define SYS_CTRL_RST_COPRO 1 +#define SYS_CTRL_RST_ARM0 2 +#define SYS_CTRL_RST_ARM1 3 +#define SYS_CTRL_RST_USBHS 4 +#define SYS_CTRL_RST_USBHSPHYA 5 +#define SYS_CTRL_RST_MACA 6 +#define SYS_CTRL_RST_MAC SYS_CTRL_RST_MACA +#define SYS_CTRL_RST_PCIEA 7 +#define SYS_CTRL_RST_SGDMA 8 +#define SYS_CTRL_RST_CIPHER 9 +#define SYS_CTRL_RST_DDR 10 +#define SYS_CTRL_RST_SATA 11 +#define SYS_CTRL_RST_SATA_LINK 12 +#define SYS_CTRL_RST_SATA_PHY 13 +#define SYS_CTRL_RST_PCIEPHY 14 +#define SYS_CTRL_RST_STATIC 15 +#define SYS_CTRL_RST_GPIO 16 +#define SYS_CTRL_RST_UART1 17 +#define SYS_CTRL_RST_UART2 18 +#define SYS_CTRL_RST_MISC 19 +#define SYS_CTRL_RST_I2S 20 +#define SYS_CTRL_RST_SD 21 +#define SYS_CTRL_RST_MACB 22 +#define SYS_CTRL_RST_PCIEB 23 +#define SYS_CTRL_RST_VIDEO 24 +#define SYS_CTRL_RST_DDR_PHY 25 +#define SYS_CTRL_RST_USBHSPHYB 26 +#define SYS_CTRL_RST_USBDEV 27 +#define SYS_CTRL_RST_ARMDBG 29 +#define SYS_CTRL_RST_PLLA 30 +#define SYS_CTRL_RST_PLLB 31 + +static inline void oxnas_register_clear_mask(void __iomem *p, unsigned mask) +{ + u32 val = readl_relaxed(p); + + val &= ~mask; + writel_relaxed(val, p); +} + +static inline void oxnas_register_set_mask(void __iomem *p, unsigned mask) +{ + u32 val = readl_relaxed(p); + + val |= mask; + writel_relaxed(val, p); +} + +static inline void oxnas_register_value_mask(void __iomem *p, + unsigned mask, unsigned new_value) +{ + /* TODO sanity check mask & new_value = new_value */ + u32 val = readl_relaxed(p); + + val &= ~mask; + val |= new_value; + writel_relaxed(val, p); +} #define VERSION_ID_MAGIC 0x082510b5 #define LINK_UP_TIMEOUT_SECONDS 1 diff --git a/target/linux/oxnas/files/drivers/pinctrl/pinctrl-oxnas.c b/target/linux/oxnas/files/drivers/pinctrl/pinctrl-oxnas.c deleted file mode 100644 index 38a8cbb451..0000000000 --- a/target/linux/oxnas/files/drivers/pinctrl/pinctrl-oxnas.c +++ /dev/null @@ -1,1461 +0,0 @@ -/* - * oxnas pinctrl driver based on at91 pinctrl driver - * - * Copyright (C) 2011-2012 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com> - * - * Under GPLv2 only - */ -#include <linux/clk.h> -#include <linux/err.h> -#include <linux/init.h> -#include <linux/module.h> -#include <linux/of.h> -#include <linux/of_device.h> -#include <linux/of_address.h> -#include <linux/of_irq.h> -#include <linux/slab.h> -#include <linux/interrupt.h> -#include <linux/irq.h> -#include <linux/irqdomain.h> -#include <linux/irqchip/chained_irq.h> -#include <linux/io.h> -#include <linux/gpio.h> -#include <linux/pinctrl/machine.h> -#include <linux/pinctrl/pinconf.h> -#include <linux/pinctrl/pinctrl.h> -#include <linux/pinctrl/pinmux.h> -/* Since we request GPIOs from ourself */ -#include <linux/pinctrl/consumer.h> -#include <linux/spinlock.h> - -#include "core.h" - -#include <mach/utils.h> - -#define MAX_NB_GPIO_PER_BANK 32 -#define MAX_GPIO_BANKS 2 - -struct oxnas_gpio_chip { - struct gpio_chip chip; - struct pinctrl_gpio_range range; - void __iomem *regbase; /* GPIOA/B virtual address */ - void __iomem *ctrlbase; /* SYS/SEC_CTRL virtual address */ - struct irq_domain *domain; /* associated irq domain */ - spinlock_t lock; -}; - -#define to_oxnas_gpio_chip(c) container_of(c, struct oxnas_gpio_chip, chip) - -static struct oxnas_gpio_chip *gpio_chips[MAX_GPIO_BANKS]; - -static int gpio_banks; - -#define PULL_UP (1 << 0) -#define PULL_DOWN (1 << 1) -#define DEBOUNCE (1 << 2) - -/** - * struct oxnas_pmx_func - describes pinmux functions - * @name: the name of this specific function - * @groups: corresponding pin groups - * @ngroups: the number of groups - */ -struct oxnas_pmx_func { - const char *name; - const char **groups; - unsigned ngroups; -}; - -enum oxnas_mux { - OXNAS_PINMUX_GPIO, - OXNAS_PINMUX_FUNC2, - OXNAS_PINMUX_FUNC3, - OXNAS_PINMUX_FUNC4, - OXNAS_PINMUX_DEBUG, - OXNAS_PINMUX_ALT, -}; - -enum { - INPUT_VALUE = 0, - OUTPUT_ENABLE = 4, - IRQ_PENDING = 0xC, - OUTPUT_VALUE = 0x10, - OUTPUT_SET = 0x14, - OUTPUT_CLEAR = 0x18, - OUTPUT_EN_SET = 0x1C, - OUTPUT_EN_CLEAR = 0x20, - DEBOUNCE_ENABLE = 0x24, - RE_IRQ_ENABLE = 0x28, /* rising edge */ - FE_IRQ_ENABLE = 0x2C, /* falling edge */ - RE_IRQ_PENDING = 0x30, /* rising edge */ - FE_IRQ_PENDING = 0x34, /* falling edge */ - CLOCK_DIV = 0x48, - PULL_ENABLE = 0x50, - PULL_SENSE = 0x54, /* 1 up, 0 down */ - - - DEBOUNCE_MASK = 0x3FFF0000, - /* put hw debounce and soft config at same bit position*/ - DEBOUNCE_SHIFT = 16 -}; - -enum { - PINMUX_SECONDARY_SEL = 0x14, - PINMUX_TERTIARY_SEL = 0x8c, - PINMUX_QUATERNARY_SEL = 0x94, - PINMUX_DEBUG_SEL = 0x9c, - PINMUX_ALTERNATIVE_SEL = 0xa4, - PINMUX_PULLUP_SEL = 0xac, -}; - -/** - * struct oxnas_pmx_pin - describes an pin mux - * @bank: the bank of the pin - * @pin: the pin number in the @bank - * @mux: the mux mode : gpio or periph_x of the pin i.e. alternate function. - * @conf: the configuration of the pin: PULL_UP, MULTIDRIVE etc... - */ -struct oxnas_pmx_pin { - uint32_t bank; - uint32_t pin; - enum oxnas_mux mux; - unsigned long conf; -}; - -/** - * struct oxnas_pin_group - describes an pin group - * @name: the name of this specific pin group - * @pins_conf: the mux mode for each pin in this group. The size of this - * array is the same as pins. - * @pins: an array of discrete physical pins used in this group, taken - * from the driver-local pin enumeration space - * @npins: the number of pins in this group array, i.e. the number of - * elements in .pins so we can iterate over that array - */ -struct oxnas_pin_group { - const char *name; - struct oxnas_pmx_pin *pins_conf; - unsigned int *pins; - unsigned npins; -}; - -struct oxnas_pinctrl { - struct device *dev; - struct pinctrl_dev *pctl; - - int nbanks; - - uint32_t *mux_mask; - int nmux; - - struct oxnas_pmx_func *functions; - int nfunctions; - - struct oxnas_pin_group *groups; - int ngroups; -}; - -static const inline struct oxnas_pin_group *oxnas_pinctrl_find_group_by_name( - const struct oxnas_pinctrl *info, - const char *name) -{ - const struct oxnas_pin_group *grp = NULL; - int i; - - for (i = 0; i < info->ngroups; i++) { - if (strcmp(info->groups[i].name, name)) - continue; - - grp = &info->groups[i]; - dev_dbg(info->dev, "%s: %d 0:%d\n", name, grp->npins, - grp->pins[0]); - break; - } - - return grp; -} - -static int oxnas_get_groups_count(struct pinctrl_dev *pctldev) -{ - struct oxnas_pinctrl *info = pinctrl_dev_get_drvdata(pctldev); - - return info->ngroups; -} - -static const char *oxnas_get_group_name(struct pinctrl_dev *pctldev, - unsigned selector) -{ - struct oxnas_pinctrl *info = pinctrl_dev_get_drvdata(pctldev); - - return info->groups[selector].name; -} - -static int oxnas_get_group_pins(struct pinctrl_dev *pctldev, unsigned selector, - const unsigned **pins, - unsigned *npins) -{ - struct oxnas_pinctrl *info = pinctrl_dev_get_drvdata(pctldev); - - if (selector >= info->ngroups) - return -EINVAL; - - *pins = info->groups[selector].pins; - *npins = info->groups[selector].npins; - - return 0; -} - -static void oxnas_pin_dbg_show(struct pinctrl_dev *pctldev, struct seq_file *s, - unsigned offset) -{ - seq_printf(s, "%s", dev_name(pctldev->dev)); -} - -static int oxnas_dt_node_to_map(struct pinctrl_dev *pctldev, - struct device_node *np, - struct pinctrl_map **map, unsigned *num_maps) -{ - struct oxnas_pinctrl *info = pinctrl_dev_get_drvdata(pctldev); - const struct oxnas_pin_group *grp; - struct pinctrl_map *new_map; - struct device_node *parent; - int map_num = 1; - int i; - - /* - * first find the group of this node and check if we need create - * config maps for pins - */ - grp = oxnas_pinctrl_find_group_by_name(info, np->name); - if (!grp) { - dev_err(info->dev, "unable to find group for node %s\n", - np->name); - return -EINVAL; - } - - map_num += grp->npins; - new_map = devm_kzalloc(pctldev->dev, sizeof(*new_map) * map_num, - GFP_KERNEL); - if (!new_map) - return -ENOMEM; - - *map = new_map; - *num_maps = map_num; - - /* create mux map */ - parent = of_get_parent(np); - if (!parent) { - devm_kfree(pctldev->dev, new_map); - return -EINVAL; - } - new_map[0].type = PIN_MAP_TYPE_MUX_GROUP; - new_map[0].data.mux.function = parent->name; - new_map[0].data.mux.group = np->name; - of_node_put(parent); - - /* create config map */ - new_map++; - for (i = 0; i < grp->npins; i++) { - new_map[i].type = PIN_MAP_TYPE_CONFIGS_PIN; - new_map[i].data.configs.group_or_pin = - pin_get_name(pctldev, grp->pins[i]); - new_map[i].data.configs.configs = &grp->pins_conf[i].conf; - new_map[i].data.configs.num_configs = 1; - } - - dev_dbg(pctldev->dev, "maps: function %s group %s num %d\n", - (*map)->data.mux.function, (*map)->data.mux.group, map_num); - - return 0; -} - -static void oxnas_dt_free_map(struct pinctrl_dev *pctldev, - struct pinctrl_map *map, unsigned num_maps) -{ -} - -static const struct pinctrl_ops oxnas_pctrl_ops = { - .get_groups_count = oxnas_get_groups_count, - .get_group_name = oxnas_get_group_name, - .get_group_pins = oxnas_get_group_pins, - .pin_dbg_show = oxnas_pin_dbg_show, - .dt_node_to_map = oxnas_dt_node_to_map, - .dt_free_map = oxnas_dt_free_map, -}; - -static void __iomem *pin_to_gpioctrl(struct oxnas_pinctrl *info, - unsigned int bank) -{ - return gpio_chips[bank]->regbase; -} - -static void __iomem *pin_to_muxctrl(struct oxnas_pinctrl *info, - unsigned int bank) -{ - return gpio_chips[bank]->ctrlbase; -} - - -static inline int pin_to_bank(unsigned pin) -{ - return pin / MAX_NB_GPIO_PER_BANK; -} - -static unsigned pin_to_mask(unsigned int pin) -{ - return 1 << pin; -} - -static void oxnas_mux_disable_interrupt(void __iomem *pio, unsigned mask) -{ - oxnas_register_clear_mask(pio + RE_IRQ_ENABLE, mask); - oxnas_register_clear_mask(pio + FE_IRQ_ENABLE, mask); -} - -static unsigned oxnas_mux_get_pullup(void __iomem *pio, unsigned pin) -{ - return (readl_relaxed(pio + PULL_ENABLE) & BIT(pin)) && - (readl_relaxed(pio + PULL_SENSE) & BIT(pin)); -} - -static void oxnas_mux_set_pullup(void __iomem *pio, unsigned mask, bool on) -{ - if (on) { - oxnas_register_set_mask(pio + PULL_SENSE, mask); - oxnas_register_set_mask(pio + PULL_ENABLE, mask); - } else { - oxnas_register_clear_mask(pio + PULL_ENABLE, mask); - } -} - -static bool oxnas_mux_get_pulldown(void __iomem *pio, unsigned pin) -{ - return (readl_relaxed(pio + PULL_ENABLE) & BIT(pin)) && - (!(readl_relaxed(pio + PULL_SENSE) & BIT(pin))); -} - -static void oxnas_mux_set_pulldown(void __iomem *pio, unsigned mask, bool on) -{ - if (on) { - oxnas_register_clear_mask(pio + PULL_SENSE, mask); - oxnas_register_set_mask(pio + PULL_ENABLE, mask); - } else { - oxnas_register_clear_mask(pio + PULL_ENABLE, mask); - }; -} - -/* unfortunately debounce control are shared */ -static bool oxnas_mux_get_debounce(void __iomem *pio, unsigned pin, u32 *div) -{ - *div = __raw_readl(pio + CLOCK_DIV) & DEBOUNCE_MASK; - return __raw_readl(pio + DEBOUNCE_ENABLE) & BIT(pin); -} - -static void oxnas_mux_set_debounce(void __iomem *pio, unsigned mask, - bool is_on, u32 div) -{ - if (is_on) { - oxnas_register_value_mask(pio + CLOCK_DIV, DEBOUNCE_MASK, div); - oxnas_register_set_mask(pio + DEBOUNCE_ENABLE, mask); - } else { - oxnas_register_clear_mask(pio + DEBOUNCE_ENABLE, mask); - } -} - - -static void oxnas_mux_set_func2(void __iomem *cio, unsigned mask) -{ -/* in fact, SECONDARY takes precedence, so clear others is not necessary */ - oxnas_register_set_mask(cio + PINMUX_SECONDARY_SEL, mask); - oxnas_register_clear_mask(cio + PINMUX_TERTIARY_SEL, mask); - oxnas_register_clear_mask(cio + PINMUX_QUATERNARY_SEL, mask); - oxnas_register_clear_mask(cio + PINMUX_DEBUG_SEL, mask); - oxnas_register_clear_mask(cio + PINMUX_ALTERNATIVE_SEL, mask); -} - -static void oxnas_mux_set_func3(void __iomem *cio, unsigned mask) -{ - oxnas_register_clear_mask(cio + PINMUX_SECONDARY_SEL, mask); - oxnas_register_set_mask(cio + PINMUX_TERTIARY_SEL, mask); - oxnas_register_clear_mask(cio + PINMUX_QUATERNARY_SEL, mask); - oxnas_register_clear_mask(cio + PINMUX_DEBUG_SEL, mask); - oxnas_register_clear_mask(cio + PINMUX_ALTERNATIVE_SEL, mask); -} - -static void oxnas_mux_set_func4(void __iomem *cio, unsigned mask) -{ - oxnas_register_clear_mask(cio + PINMUX_SECONDARY_SEL, mask); - oxnas_register_clear_mask(cio + PINMUX_TERTIARY_SEL, mask); - oxnas_register_set_mask(cio + PINMUX_QUATERNARY_SEL, mask); - oxnas_register_clear_mask(cio + PINMUX_DEBUG_SEL, mask); - oxnas_register_clear_mask(cio + PINMUX_ALTERNATIVE_SEL, mask); -} - -static void oxnas_mux_set_func_dbg(void __iomem *cio, unsigned mask) -{ - oxnas_register_clear_mask(cio + PINMUX_SECONDARY_SEL, mask); - oxnas_register_clear_mask(cio + PINMUX_TERTIARY_SEL, mask); - oxnas_register_clear_mask(cio + PINMUX_QUATERNARY_SEL, mask); - oxnas_register_set_mask(cio + PINMUX_DEBUG_SEL, mask); - oxnas_register_clear_mask(cio + PINMUX_ALTERNATIVE_SEL, mask); -} - -static void oxnas_mux_set_func_alt(void __iomem *cio, unsigned mask) -{ - oxnas_register_clear_mask(cio + PINMUX_SECONDARY_SEL, mask); - oxnas_register_clear_mask(cio + PINMUX_TERTIARY_SEL, mask); - oxnas_register_clear_mask(cio + PINMUX_QUATERNARY_SEL, mask); - oxnas_register_clear_mask(cio + PINMUX_DEBUG_SEL, mask); - oxnas_register_set_mask(cio + PINMUX_ALTERNATIVE_SEL, mask); -} - -static void oxnas_mux_set_gpio(void __iomem *cio, unsigned mask) -{ - oxnas_register_clear_mask(cio + PINMUX_SECONDARY_SEL, mask); - oxnas_register_clear_mask(cio + PINMUX_TERTIARY_SEL, mask); - oxnas_register_clear_mask(cio + PINMUX_QUATERNARY_SEL, mask); - oxnas_register_clear_mask(cio + PINMUX_DEBUG_SEL, mask); - oxnas_register_clear_mask(cio + PINMUX_ALTERNATIVE_SEL, mask); -} - -static enum oxnas_mux oxnas_mux_get_func(void __iomem *cio, unsigned mask) -{ - if (readl_relaxed(cio + PINMUX_SECONDARY_SEL) & mask) - return OXNAS_PINMUX_FUNC2; - if (readl_relaxed(cio + PINMUX_TERTIARY_SEL) & mask) - return OXNAS_PINMUX_FUNC3; - if (readl_relaxed(cio + PINMUX_QUATERNARY_SEL) & mask) - return OXNAS_PINMUX_FUNC4; - if (readl_relaxed(cio + PINMUX_DEBUG_SEL) & mask) - return OXNAS_PINMUX_DEBUG; - if (readl_relaxed(cio + PINMUX_ALTERNATIVE_SEL) & mask) - return OXNAS_PINMUX_ALT; - return OXNAS_PINMUX_GPIO; -} - - -static void oxnas_pin_dbg(const struct device *dev, - const struct oxnas_pmx_pin *pin) -{ - if (pin->mux) { - dev_dbg(dev, - "MF_%c%d configured as periph%c with conf = 0x%lu\n", - pin->bank + 'A', pin->pin, pin->mux - 1 + 'A', - pin->conf); - } else { - dev_dbg(dev, "MF_%c%d configured as gpio with conf = 0x%lu\n", - pin->bank + 'A', pin->pin, pin->conf); - } -} - -static int pin_check_config(struct oxnas_pinctrl *info, const char *name, - int index, const struct oxnas_pmx_pin *pin) -{ - int mux; - - /* check if it's a valid config */ - if (pin->bank >= info->nbanks) { - dev_err(info->dev, "%s: pin conf %d bank_id %d >= nbanks %d\n", - name, index, pin->bank, info->nbanks); - return -EINVAL; - } - - if (pin->pin >= MAX_NB_GPIO_PER_BANK) { - dev_err(info->dev, "%s: pin conf %d pin_bank_id %d >= %d\n", - name, index, pin->pin, MAX_NB_GPIO_PER_BANK); - return -EINVAL; - } - /* gpio always allowed */ - if (!pin->mux) - return 0; - - mux = pin->mux - 1; - - if (mux >= info->nmux) { - dev_err(info->dev, "%s: pin conf %d mux_id %d >= nmux %d\n", - name, index, mux, info->nmux); - return -EINVAL; - } - - if (!(info->mux_mask[pin->bank * info->nmux + mux] & 1 << pin->pin)) { - dev_err(info->dev, "%s: pin conf %d mux_id %d not supported for MF_%c%d\n", - name, index, mux, pin->bank + 'A', pin->pin); - return -EINVAL; - } - - return 0; -} - -static void oxnas_mux_gpio_enable(void __iomem *cio, void __iomem *pio, - unsigned mask, bool input) -{ - oxnas_mux_set_gpio(cio, mask); - if (input) - writel_relaxed(mask, pio + OUTPUT_EN_CLEAR); - else - writel_relaxed(mask, pio + OUTPUT_EN_SET); -} - -static void oxnas_mux_gpio_disable(void __iomem *cio, void __iomem *pio, - unsigned mask) -{ - /* when switch to other function, gpio is disabled automatically */ - return; -} - -static int oxnas_pmx_set_mux(struct pinctrl_dev *pctldev, unsigned selector, - unsigned group) -{ - struct oxnas_pinctrl *info = pinctrl_dev_get_drvdata(pctldev); - const struct oxnas_pmx_pin *pins_conf = info->groups[group].pins_conf; - const struct oxnas_pmx_pin *pin; - uint32_t npins = info->groups[group].npins; - int i, ret; - unsigned mask; - void __iomem *pio; - void __iomem *cio; - - dev_dbg(info->dev, "enable function %s group %s\n", - info->functions[selector].name, info->groups[group].name); - - /* first check that all the pins of the group are valid with a valid - * paramter */ - for (i = 0; i < npins; i++) { - pin = &pins_conf[i]; - ret = pin_check_config(info, info->groups[group].name, i, pin); - if (ret) - return ret; - } - - for (i = 0; i < npins; i++) { - pin = &pins_conf[i]; - oxnas_pin_dbg(info->dev, pin); - - pio = pin_to_gpioctrl(info, pin->bank); - cio = pin_to_muxctrl(info, pin->bank); - - mask = pin_to_mask(pin->pin); - oxnas_mux_disable_interrupt(pio, mask); - - switch (pin->mux) { - case OXNAS_PINMUX_GPIO: - oxnas_mux_gpio_enable(cio, pio, mask, 1); - break; - case OXNAS_PINMUX_FUNC2: - oxnas_mux_set_func2(cio, mask); - break; - case OXNAS_PINMUX_FUNC3: - oxnas_mux_set_func3(cio, mask); - break; - case OXNAS_PINMUX_FUNC4: - oxnas_mux_set_func4(cio, mask); - break; - case OXNAS_PINMUX_DEBUG: - oxnas_mux_set_func_dbg(cio, mask); - break; - case OXNAS_PINMUX_ALT: - oxnas_mux_set_func_alt(cio, mask); - break; - } - if (pin->mux) - oxnas_mux_gpio_disable(cio, pio, mask); - } - - return 0; -} - -static int oxnas_pmx_get_funcs_count(struct pinctrl_dev *pctldev) -{ - struct oxnas_pinctrl *info = pinctrl_dev_get_drvdata(pctldev); - - return info->nfunctions; -} - -static const char *oxnas_pmx_get_func_name(struct pinctrl_dev *pctldev, - unsigned selector) -{ - struct oxnas_pinctrl *info = pinctrl_dev_get_drvdata(pctldev); - - return info->functions[selector].name; -} - -static int oxnas_pmx_get_groups(struct pinctrl_dev *pctldev, unsigned selector, - const char * const **groups, - unsigned * const num_groups) -{ - struct oxnas_pinctrl *info = pinctrl_dev_get_drvdata(pctldev); - - *groups = info->functions[selector].groups; - *num_groups = info->functions[selector].ngroups; - - return 0; -} - -static int oxnas_gpio_request_enable(struct pinctrl_dev *pctldev, - struct pinctrl_gpio_range *range, - unsigned offset) -{ - struct oxnas_pinctrl *npct = pinctrl_dev_get_drvdata(pctldev); - struct oxnas_gpio_chip *oxnas_chip; - struct gpio_chip *chip; - unsigned mask; - - if (!range) { - dev_err(npct->dev, "invalid range\n"); - return -EINVAL; - } - if (!range->gc) { - dev_err(npct->dev, "missing GPIO chip in range\n"); - return -EINVAL; - } - chip = range->gc; - oxnas_chip = container_of(chip, struct oxnas_gpio_chip, chip); - - dev_dbg(npct->dev, "enable pin %u as GPIO\n", offset); - - mask = 1 << (offset - chip->base); - - dev_dbg(npct->dev, "enable pin %u as MF_%c%d 0x%x\n", - offset, 'A' + range->id, offset - chip->base, mask); - - oxnas_mux_set_gpio(oxnas_chip->ctrlbase, mask); - - return 0; -} - -static void oxnas_gpio_disable_free(struct pinctrl_dev *pctldev, - struct pinctrl_gpio_range *range, - unsigned offset) -{ - struct oxnas_pinctrl *npct = pinctrl_dev_get_drvdata(pctldev); - - dev_dbg(npct->dev, "disable pin %u as GPIO\n", offset); - /* Set the pin to some default state, GPIO is usually default */ -} - -static const struct pinmux_ops oxnas_pmx_ops = { - .get_functions_count = oxnas_pmx_get_funcs_count, - .get_function_name = oxnas_pmx_get_func_name, - .get_function_groups = oxnas_pmx_get_groups, - .set_mux = oxnas_pmx_set_mux, - .gpio_request_enable = oxnas_gpio_request_enable, - .gpio_disable_free = oxnas_gpio_disable_free, -}; - -static int oxnas_pinconf_get(struct pinctrl_dev *pctldev, - unsigned pin_id, unsigned long *config) -{ - struct oxnas_pinctrl *info = pinctrl_dev_get_drvdata(pctldev); - void __iomem *pio; - unsigned pin; - int div; - - dev_dbg(info->dev, "%s:%d, pin_id=%d, config=0x%lx", __func__, - __LINE__, pin_id, *config); - pio = pin_to_gpioctrl(info, pin_to_bank(pin_id)); - pin = pin_id % MAX_NB_GPIO_PER_BANK; - - if (oxnas_mux_get_pullup(pio, pin)) - *config |= PULL_UP; - - if (oxnas_mux_get_pulldown(pio, pin)) - *config |= PULL_DOWN; - - if (oxnas_mux_get_debounce(pio, pin, &div)) - *config |= DEBOUNCE | div; - return 0; -} - -static int oxnas_pinconf_set(struct pinctrl_dev *pctldev, - unsigned pin_id, unsigned long *configs, - unsigned num_configs) -{ - struct oxnas_pinctrl *info = pinctrl_dev_get_drvdata(pctldev); - unsigned mask; - void __iomem *pio; - int i; - unsigned long config; - - pio = pin_to_gpioctrl(info, pin_to_bank(pin_id)); - mask = pin_to_mask(pin_id % MAX_NB_GPIO_PER_BANK); - - for (i = 0; i < num_configs; i++) { - config = configs[i]; - - dev_dbg(info->dev, - "%s:%d, pin_id=%d, config=0x%lx", - __func__, __LINE__, pin_id, config); - - if ((config & PULL_UP) && (config & PULL_DOWN)) - return -EINVAL; - - oxnas_mux_set_pullup(pio, mask, config & PULL_UP); - oxnas_mux_set_pulldown(pio, mask, config & PULL_DOWN); - oxnas_mux_set_debounce(pio, mask, config & DEBOUNCE, - config & DEBOUNCE_MASK); - - } /* for each config */ - - return 0; -} - -static void oxnas_pinconf_dbg_show(struct pinctrl_dev *pctldev, - struct seq_file *s, unsigned pin_id) -{ - -} - -static void oxnas_pinconf_group_dbg_show(struct pinctrl_dev *pctldev, - struct seq_file *s, unsigned group) -{ -} - -static const struct pinconf_ops oxnas_pinconf_ops = { - .pin_config_get = oxnas_pinconf_get, - .pin_config_set = oxnas_pinconf_set, - .pin_config_dbg_show = oxnas_pinconf_dbg_show, - .pin_config_group_dbg_show = oxnas_pinconf_group_dbg_show, -}; - -static struct pinctrl_desc oxnas_pinctrl_desc = { - .pctlops = &oxnas_pctrl_ops, - .pmxops = &oxnas_pmx_ops, - .confops = &oxnas_pinconf_ops, - .owner = THIS_MODULE, -}; - -static const char *gpio_compat = "plxtech,nas782x-gpio"; - -static void oxnas_pinctrl_child_count(struct oxnas_pinctrl *info, - struct device_node *np) -{ - struct device_node *child; - - for_each_child_of_node(np, child) { - if (of_device_is_compatible(child, gpio_compat)) { - info->nbanks++; - } else { - info->nfunctions++; - info->ngroups += of_get_child_count(child); - } - } -} - -static int oxnas_pinctrl_mux_mask(struct oxnas_pinctrl *info, - struct device_node *np) -{ - int ret = 0; - int size; - const __be32 *list; - - list = of_get_property(np, "plxtech,mux-mask", &size); - if (!list) { - dev_err(info->dev, "can not read the mux-mask of %d\n", size); - return -EINVAL; - } - - size /= sizeof(*list); - if (!size || size % info->nbanks) { - dev_err(info->dev, "wrong mux mask array should be by %d\n", - info->nbanks); - return -EINVAL; - } - info->nmux = size / info->nbanks; - - info->mux_mask = devm_kzalloc(info->dev, sizeof(u32) * size, GFP_KERNEL); - if (!info->mux_mask) { - dev_err(info->dev, "could not alloc mux_mask\n"); - return -ENOMEM; - } - - ret = of_property_read_u32_array(np, "plxtech,mux-mask", - info->mux_mask, size); - if (ret) - dev_err(info->dev, "can not read the mux-mask of %d\n", size); - return ret; -} - -static int oxnas_pinctrl_parse_groups(struct device_node *np, - struct oxnas_pin_group *grp, - struct oxnas_pinctrl *info, u32 index) -{ - struct oxnas_pmx_pin *pin; - int size; - const __be32 *list; - int i, j; - - dev_dbg(info->dev, "group(%d): %s\n", index, np->name); - - /* Initialise group */ - grp->name = np->name; - - /* - * the binding format is plxtech,pins = <bank pin mux CONFIG ...>, - * do sanity check and calculate pins number - */ - list = of_get_property(np, "plxtech,pins", &size); - /* we do not check return since it's safe node passed down */ - size /= sizeof(*list); - if (!size || size % 4) { - dev_err(info->dev, "wrong pins number or pins and configs" - " should be divisible by 4\n"); - return -EINVAL; - } - - grp->npins = size / 4; - pin = grp->pins_conf = devm_kzalloc(info->dev, - grp->npins * sizeof(struct oxnas_pmx_pin), - GFP_KERNEL); - grp->pins = devm_kzalloc(info->dev, grp->npins * sizeof(unsigned int), - GFP_KERNEL); - if (!grp->pins_conf || !grp->pins) - return -ENOMEM; - - for (i = 0, j = 0; i < size; i += 4, j++) { - pin->bank = be32_to_cpu(*list++); - pin->pin = be32_to_cpu(*list++); - grp->pins[j] = pin->bank * MAX_NB_GPIO_PER_BANK + pin->pin; - pin->mux = be32_to_cpu(*list++); - pin->conf = be32_to_cpu(*list++); - - oxnas_pin_dbg(info->dev, pin); - pin++; - } - - return 0; -} - -static int oxnas_pinctrl_parse_functions(struct device_node *np, - struct oxnas_pinctrl *info, u32 index) -{ - struct device_node *child; - struct oxnas_pmx_func *func; - struct oxnas_pin_group *grp; - int ret; - static u32 grp_index; - u32 i = 0; - - dev_dbg(info->dev, "parse function(%d): %s\n", index, np->name); - - func = &info->functions[index]; - - /* Initialise function */ - func->name = np->name; - func->ngroups = of_get_child_count(np); - if (func->ngroups <= 0) { - dev_err(info->dev, "no groups defined\n"); - return -EINVAL; - } - func->groups = devm_kzalloc(info->dev, - func->ngroups * sizeof(char *), GFP_KERNEL); - if (!func->groups) - return -ENOMEM; - - for_each_child_of_node(np, child) { - func->groups[i] = child->name; - grp = &info->groups[grp_index++]; - ret = oxnas_pinctrl_parse_groups(child, grp, info, i++); - if (ret) - return ret; - } - - return 0; -} - -static struct of_device_id oxnas_pinctrl_of_match[] = { - { .compatible = "plxtech,nas782x-pinctrl"}, - { /* sentinel */ } -}; - -static int oxnas_pinctrl_probe_dt(struct platform_device *pdev, - struct oxnas_pinctrl *info) -{ - int ret = 0; - int i, j; - uint32_t *tmp; - struct device_node *np = pdev->dev.of_node; - struct device_node *child; - - if (!np) - return -ENODEV; - - info->dev = &pdev->dev; - - oxnas_pinctrl_child_count(info, np); - - if (info->nbanks < 1) { - dev_err(&pdev->dev, "you need to specify atleast one gpio-controller\n"); - return -EINVAL; - } - - ret = oxnas_pinctrl_mux_mask(info, np); - if (ret) - return ret; - - dev_dbg(&pdev->dev, "nmux = %d\n", info->nmux); - - dev_dbg(&pdev->dev, "mux-mask\n"); - tmp = info->mux_mask; - for (i = 0; i < info->nbanks; i++) - for (j = 0; j < info->nmux; j++, tmp++) - dev_dbg(&pdev->dev, "%d:%d\t0x%x\n", i, j, tmp[0]); - - dev_dbg(&pdev->dev, "nfunctions = %d\n", info->nfunctions); - dev_dbg(&pdev->dev, "ngroups = %d\n", info->ngroups); - info->functions = devm_kzalloc(&pdev->dev, info->nfunctions * - sizeof(struct oxnas_pmx_func), - GFP_KERNEL); - if (!info->functions) - return -ENOMEM; - - info->groups = devm_kzalloc(&pdev->dev, info->ngroups * - sizeof(struct oxnas_pin_group), - GFP_KERNEL); - if (!info->groups) - return -ENOMEM; - - dev_dbg(&pdev->dev, "nbanks = %d\n", info->nbanks); - dev_dbg(&pdev->dev, "nfunctions = %d\n", info->nfunctions); - dev_dbg(&pdev->dev, "ngroups = %d\n", info->ngroups); - - i = 0; - - for_each_child_of_node(np, child) { - if (of_device_is_compatible(child, gpio_compat)) - continue; - ret = oxnas_pinctrl_parse_functions(child, info, i++); - if (ret) { - dev_err(&pdev->dev, "failed to parse function\n"); - return ret; - } - } - - return 0; -} - -static int oxnas_pinctrl_probe(struct platform_device *pdev) -{ - struct oxnas_pinctrl *info; - struct pinctrl_pin_desc *pdesc; - int ret, i, j, k; - - info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL); - if (!info) - return -ENOMEM; - - ret = oxnas_pinctrl_probe_dt(pdev, info); - if (ret) - return ret; - - /* - * We need all the GPIO drivers to probe FIRST, or we will not be able - * to obtain references to the struct gpio_chip * for them, and we - * need this to proceed. - */ - for (i = 0; i < info->nbanks; i++) { - if (!gpio_chips[i]) { - dev_warn(&pdev->dev, - "GPIO chip %d not registered yet\n", i); - devm_kfree(&pdev->dev, info); - return -EPROBE_DEFER; - } - } - - oxnas_pinctrl_desc.name = dev_name(&pdev->dev); - oxnas_pinctrl_desc.npins = info->nbanks * MAX_NB_GPIO_PER_BANK; - oxnas_pinctrl_desc.pins = pdesc = - devm_kzalloc(&pdev->dev, sizeof(*pdesc) * - oxnas_pinctrl_desc.npins, GFP_KERNEL); - - if (!oxnas_pinctrl_desc.pins) - return -ENOMEM; - - for (i = 0 , k = 0; i < info->nbanks; i++) { - for (j = 0; j < MAX_NB_GPIO_PER_BANK; j++, k++) { - pdesc->number = k; - pdesc->name = kasprintf(GFP_KERNEL, "MF_%c%d", i + 'A', - j); - pdesc++; - } - } - - platform_set_drvdata(pdev, info); - info->pctl = pinctrl_register(&oxnas_pinctrl_desc, &pdev->dev, info); - - if (!info->pctl) { - dev_err(&pdev->dev, "could not register OX820 pinctrl driver\n"); - ret = -EINVAL; - goto err; - } - - /* We will handle a range of GPIO pins */ - for (i = 0; i < info->nbanks; i++) - pinctrl_add_gpio_range(info->pctl, &gpio_chips[i]->range); - - dev_info(&pdev->dev, "initialized OX820 pinctrl driver\n"); - - return 0; - -err: - return ret; -} - -static int oxnas_pinctrl_remove(struct platform_device *pdev) -{ - struct oxnas_pinctrl *info = platform_get_drvdata(pdev); - - pinctrl_unregister(info->pctl); - - return 0; -} - -static int oxnas_gpio_request(struct gpio_chip *chip, unsigned offset) -{ - /* - * Map back to global GPIO space and request muxing, the direction - * parameter does not matter for this controller. - */ - int gpio = chip->base + offset; - int bank = chip->base / chip->ngpio; - - dev_dbg(chip->dev, "%s:%d MF_%c%d(%d)\n", __func__, __LINE__, - 'A' + bank, offset, gpio); - - return pinctrl_request_gpio(gpio); -} - -static void oxnas_gpio_free(struct gpio_chip *chip, unsigned offset) -{ - int gpio = chip->base + offset; - - pinctrl_free_gpio(gpio); -} - -static int oxnas_gpio_direction_input(struct gpio_chip *chip, unsigned offset) -{ - struct oxnas_gpio_chip *oxnas_gpio = to_oxnas_gpio_chip(chip); - void __iomem *pio = oxnas_gpio->regbase; - - writel_relaxed(BIT(offset), pio + OUTPUT_EN_CLEAR); - return 0; -} - -static int oxnas_gpio_get(struct gpio_chip *chip, unsigned offset) -{ - struct oxnas_gpio_chip *oxnas_gpio = to_oxnas_gpio_chip(chip); - void __iomem *pio = oxnas_gpio->regbase; - unsigned mask = 1 << offset; - u32 pdsr; - - pdsr = readl_relaxed(pio + INPUT_VALUE); - return (pdsr & mask) != 0; -} - -static void oxnas_gpio_set(struct gpio_chip *chip, unsigned offset, - int val) -{ - struct oxnas_gpio_chip *oxnas_gpio = to_oxnas_gpio_chip(chip); - void __iomem *pio = oxnas_gpio->regbase; - - if (val) - writel_relaxed(BIT(offset), pio + OUTPUT_SET); - else - writel_relaxed(BIT(offset), pio + OUTPUT_CLEAR); - -} - -static int oxnas_gpio_direction_output(struct gpio_chip *chip, unsigned offset, - int val) -{ - struct oxnas_gpio_chip *oxnas_gpio = to_oxnas_gpio_chip(chip); - void __iomem *pio = oxnas_gpio->regbase; - - if (val) - writel_relaxed(BIT(offset), pio + OUTPUT_SET); - else - writel_relaxed(BIT(offset), pio + OUTPUT_CLEAR); - - writel_relaxed(BIT(offset), pio + OUTPUT_EN_SET); - - return 0; -} - -static int oxnas_gpio_to_irq(struct gpio_chip *chip, unsigned offset) -{ - struct oxnas_gpio_chip *oxnas_gpio = to_oxnas_gpio_chip(chip); - int virq; - - if (offset < chip->ngpio) - virq = irq_create_mapping(oxnas_gpio->domain, offset); - else - virq = -ENXIO; - - dev_dbg(chip->dev, "%s: request IRQ for GPIO %d, return %d\n", - chip->label, offset + chip->base, virq); - return virq; -} - -#ifdef CONFIG_DEBUG_FS -static void oxnas_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip) -{ - enum oxnas_mux mode; - int i; - struct oxnas_gpio_chip *oxnas_gpio = to_oxnas_gpio_chip(chip); - void __iomem *pio = oxnas_gpio->regbase; - void __iomem *cio = oxnas_gpio->ctrlbase; - - for (i = 0; i < chip->ngpio; i++) { - unsigned pin = chip->base + i; - unsigned mask = pin_to_mask(pin); - const char *gpio_label; - u32 pdsr; - - gpio_label = gpiochip_is_requested(chip, i); - if (!gpio_label) - continue; - /* FIXME */ - mode = oxnas_mux_get_func(cio, mask); - seq_printf(s, "[%s] GPIO%s%d: ", - gpio_label, chip->label, i); - if (mode == OXNAS_PINMUX_GPIO) { - pdsr = readl_relaxed(pio + INPUT_VALUE); - - seq_printf(s, "[gpio] %s\n", - pdsr & mask ? - "set" : "clear"); - } else { - seq_printf(s, "[periph %c]\n", - mode + 'A' - 1); - } - } -} -#else -#define oxnas_gpio_dbg_show NULL -#endif - -/* Several AIC controller irqs are dispatched through this GPIO handler. - * To use any AT91_PIN_* as an externally triggered IRQ, first call - * oxnas_set_gpio_input() then maybe enable its glitch filter. - * Then just request_irq() with the pin ID; it works like any ARM IRQ - * handler. - */ - -static void gpio_irq_mask(struct irq_data *d) -{ - struct oxnas_gpio_chip *oxnas_gpio = irq_data_get_irq_chip_data(d); - void __iomem *pio = oxnas_gpio->regbase; - unsigned mask = 1 << d->hwirq; - unsigned type = irqd_get_trigger_type(d); - unsigned long flags; - - if (!(type & IRQ_TYPE_EDGE_BOTH)) - return; - - spin_lock_irqsave(&oxnas_gpio->lock, flags); - if (type & IRQ_TYPE_EDGE_RISING) - oxnas_register_clear_mask(pio + RE_IRQ_ENABLE, mask); - if (type & IRQ_TYPE_EDGE_FALLING) - oxnas_register_clear_mask(pio + FE_IRQ_ENABLE, mask); - spin_unlock_irqrestore(&oxnas_gpio->lock, flags); -} - -static void gpio_irq_unmask(struct irq_data *d) -{ - struct oxnas_gpio_chip *oxnas_gpio = irq_data_get_irq_chip_data(d); - void __iomem *pio = oxnas_gpio->regbase; - unsigned mask = 1 << d->hwirq; - unsigned type = irqd_get_trigger_type(d); - unsigned long flags; - - if (!(type & IRQ_TYPE_EDGE_BOTH)) - return; - - spin_lock_irqsave(&oxnas_gpio->lock, flags); - if (type & IRQ_TYPE_EDGE_RISING) - oxnas_register_set_mask(pio + RE_IRQ_ENABLE, mask); - if (type & IRQ_TYPE_EDGE_FALLING) - oxnas_register_set_mask(pio + FE_IRQ_ENABLE, mask); - spin_unlock_irqrestore(&oxnas_gpio->lock, flags); -} - - -static int gpio_irq_type(struct irq_data *d, unsigned type) -{ - if ((type & IRQ_TYPE_EDGE_BOTH) == 0) { - pr_warn("OX820: Unsupported type for irq %d\n", - gpio_to_irq(d->irq)); - return -EINVAL; - } - /* seems no way to set trigger type without enable irq, so leave it to unmask time */ - - return 0; -} - -static struct irq_chip gpio_irqchip = { - .name = "GPIO", - .irq_disable = gpio_irq_mask, - .irq_mask = gpio_irq_mask, - .irq_unmask = gpio_irq_unmask, - .irq_set_type = gpio_irq_type, -}; - -static void gpio_irq_handler(struct irq_desc *desc) -{ - struct irq_chip *chip = irq_desc_get_chip(desc); - struct irq_data *idata = irq_desc_get_irq_data(desc); - struct oxnas_gpio_chip *oxnas_gpio = irq_data_get_irq_chip_data(idata); - void __iomem *pio = oxnas_gpio->regbase; - unsigned long isr; - int n; - - chained_irq_enter(chip, desc); - for (;;) { - /* TODO: see if it works */ - isr = readl_relaxed(pio + IRQ_PENDING); - if (!isr) - break; - /* acks pending interrupts */ - writel_relaxed(isr, pio + IRQ_PENDING); - - for_each_set_bit(n, &isr, BITS_PER_LONG) { - generic_handle_irq(irq_find_mapping(oxnas_gpio->domain, - n)); - } - } - chained_irq_exit(chip, desc); - /* now it may re-trigger */ -} - -/* - * This lock class tells lockdep that GPIO irqs are in a different - * category than their parents, so it won't report false recursion. - */ -static struct lock_class_key gpio_lock_class; - -static int oxnas_gpio_irq_map(struct irq_domain *h, unsigned int virq, - irq_hw_number_t hw) -{ - struct oxnas_gpio_chip *oxnas_gpio = h->host_data; - - irq_set_lockdep_class(virq, &gpio_lock_class); - - irq_set_chip_and_handler(virq, &gpio_irqchip, handle_edge_irq); - irq_set_chip_data(virq, oxnas_gpio); - - return 0; -} - -static int oxnas_gpio_irq_domain_xlate(struct irq_domain *d, - struct device_node *ctrlr, - const u32 *intspec, - unsigned int intsize, - irq_hw_number_t *out_hwirq, - unsigned int *out_type) -{ - struct oxnas_gpio_chip *oxnas_gpio = d->host_data; - int ret; - int pin = oxnas_gpio->chip.base + intspec[0]; - - if (WARN_ON(intsize < 2)) - return -EINVAL; - *out_hwirq = intspec[0]; - *out_type = intspec[1] & IRQ_TYPE_SENSE_MASK; - - ret = gpio_request(pin, ctrlr->full_name); - if (ret) - return ret; - - ret = gpio_direction_input(pin); - if (ret) - return ret; - - return 0; -} - -static struct irq_domain_ops oxnas_gpio_ops = { - .map = oxnas_gpio_irq_map, - .xlate = oxnas_gpio_irq_domain_xlate, -}; - -static int oxnas_gpio_of_irq_setup(struct device_node *node, - struct oxnas_gpio_chip *oxnas_gpio, - unsigned int irq) -{ - /* Disable irqs of this controller */ - writel_relaxed(0, oxnas_gpio->regbase + RE_IRQ_ENABLE); - writel_relaxed(0, oxnas_gpio->regbase + FE_IRQ_ENABLE); - - /* Setup irq domain */ - oxnas_gpio->domain = irq_domain_add_linear(node, oxnas_gpio->chip.ngpio, - &oxnas_gpio_ops, oxnas_gpio); - if (!oxnas_gpio->domain) - panic("oxnas_gpio: couldn't allocate irq domain (DT).\n"); - - irq_set_chip_data(irq, oxnas_gpio); - irq_set_chained_handler(irq, gpio_irq_handler); - - return 0; -} - -/* This structure is replicated for each GPIO block allocated at probe time */ -static struct gpio_chip oxnas_gpio_template = { - .request = oxnas_gpio_request, - .free = oxnas_gpio_free, - .direction_input = oxnas_gpio_direction_input, - .get = oxnas_gpio_get, - .direction_output = oxnas_gpio_direction_output, - .set = oxnas_gpio_set, - .to_irq = oxnas_gpio_to_irq, - .dbg_show = oxnas_gpio_dbg_show, - .can_sleep = 0, - .ngpio = MAX_NB_GPIO_PER_BANK, -}; - -static struct of_device_id oxnas_gpio_of_match[] = { - { .compatible = "plxtech,nas782x-gpio"}, - { /* sentinel */ } -}; - -static int oxnas_gpio_probe(struct platform_device *pdev) -{ - struct device_node *np = pdev->dev.of_node; - struct resource *res; - struct oxnas_gpio_chip *oxnas_chip = NULL; - struct gpio_chip *chip; - struct pinctrl_gpio_range *range; - int ret = 0; - int irq, i; - int alias_idx = of_alias_get_id(np, "gpio"); - uint32_t ngpio; - char **names; - - BUG_ON(alias_idx >= ARRAY_SIZE(gpio_chips)); - if (gpio_chips[alias_idx]) { - ret = -EBUSY; - goto err; - } - - irq = platform_get_irq(pdev, 0); - if (irq < 0) { - ret = irq; - goto err; - } - - oxnas_chip = devm_kzalloc(&pdev->dev, sizeof(*oxnas_chip), GFP_KERNEL); - if (!oxnas_chip) { - ret = -ENOMEM; - goto err; - } - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - oxnas_chip->regbase = devm_ioremap_resource(&pdev->dev, res); - if (IS_ERR(oxnas_chip->regbase)) { - ret = PTR_ERR(oxnas_chip->regbase); - goto err; - } - - res = platform_get_resource(pdev, IORESOURCE_MEM, 1); - oxnas_chip->ctrlbase = devm_ioremap_resource(&pdev->dev, res); - if (IS_ERR(oxnas_chip->ctrlbase)) { - ret = PTR_ERR(oxnas_chip->ctrlbase); - goto err; - } - - oxnas_chip->chip = oxnas_gpio_template; - - spin_lock_init(&oxnas_chip->lock); - - chip = &oxnas_chip->chip; - chip->of_node = np; - chip->label = dev_name(&pdev->dev); - chip->dev = &pdev->dev; - chip->owner = THIS_MODULE; - chip->base = alias_idx * MAX_NB_GPIO_PER_BANK; - - if (!of_property_read_u32(np, "#gpio-lines", &ngpio)) { - if (ngpio > MAX_NB_GPIO_PER_BANK) - pr_err("oxnas_gpio.%d, gpio-nb >= %d failback to %d\n", - alias_idx, MAX_NB_GPIO_PER_BANK, - MAX_NB_GPIO_PER_BANK); - else - chip->ngpio = ngpio; - } - - names = devm_kzalloc(&pdev->dev, sizeof(char *) * chip->ngpio, - GFP_KERNEL); - - if (!names) { - ret = -ENOMEM; - goto err; - } - - for (i = 0; i < chip->ngpio; i++) - names[i] = kasprintf(GFP_KERNEL, "MF_%c%d", alias_idx + 'A', i); - - chip->names = (const char *const *)names; - - range = &oxnas_chip->range; - range->name = chip->label; - range->id = alias_idx; - range->pin_base = range->base = range->id * MAX_NB_GPIO_PER_BANK; - - range->npins = chip->ngpio; - range->gc = chip; - - ret = gpiochip_add(chip); - if (ret) - goto err; - - gpio_chips[alias_idx] = oxnas_chip; - gpio_banks = max(gpio_banks, alias_idx + 1); - - oxnas_gpio_of_irq_setup(np, oxnas_chip, irq); - - dev_info(&pdev->dev, "at address %p\n", oxnas_chip->regbase); - - return 0; -err: - dev_err(&pdev->dev, "Failure %i for GPIO %i\n", ret, alias_idx); - - return ret; -} - -static struct platform_driver oxnas_gpio_driver = { - .driver = { - .name = "gpio-oxnas", - .owner = THIS_MODULE, - .of_match_table = of_match_ptr(oxnas_gpio_of_match), - }, - .probe = oxnas_gpio_probe, -}; - -static struct platform_driver oxnas_pinctrl_driver = { - .driver = { - .name = "pinctrl-oxnas", - .owner = THIS_MODULE, - .of_match_table = of_match_ptr(oxnas_pinctrl_of_match), - }, - .probe = oxnas_pinctrl_probe, - .remove = oxnas_pinctrl_remove, -}; - -static int __init oxnas_pinctrl_init(void) -{ - int ret; - - ret = platform_driver_register(&oxnas_gpio_driver); - if (ret) - return ret; - return platform_driver_register(&oxnas_pinctrl_driver); -} -arch_initcall(oxnas_pinctrl_init); - -static void __exit oxnas_pinctrl_exit(void) -{ - platform_driver_unregister(&oxnas_pinctrl_driver); -} - -module_exit(oxnas_pinctrl_exit); -MODULE_AUTHOR("Ma Hajun <mahaijuns@gmail.com>"); -MODULE_DESCRIPTION("Plxtech Nas782x pinctrl driver"); -MODULE_LICENSE("GPL v2"); diff --git a/target/linux/oxnas/files/drivers/reset/reset-ox820.c b/target/linux/oxnas/files/drivers/reset/reset-ox820.c deleted file mode 100644 index 0a28de55f4..0000000000 --- a/target/linux/oxnas/files/drivers/reset/reset-ox820.c +++ /dev/null @@ -1,107 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - */ - -#include <linux/err.h> -#include <linux/io.h> -#include <linux/module.h> -#include <linux/of.h> -#include <linux/platform_device.h> -#include <linux/reset-controller.h> -#include <linux/slab.h> -#include <linux/types.h> -#include <mach/hardware.h> - -static int ox820_reset_reset(struct reset_controller_dev *rcdev, - unsigned long id) -{ - writel(BIT(id), SYS_CTRL_RST_SET_CTRL); - writel(BIT(id), SYS_CTRL_RST_CLR_CTRL); - return 0; -} - -static int ox820_reset_assert(struct reset_controller_dev *rcdev, - unsigned long id) -{ - writel(BIT(id), SYS_CTRL_RST_SET_CTRL); - - return 0; -} - -static int ox820_reset_deassert(struct reset_controller_dev *rcdev, - unsigned long id) -{ - writel(BIT(id), SYS_CTRL_RST_CLR_CTRL); - - return 0; -} - -static struct reset_control_ops ox820_reset_ops = { - .reset = ox820_reset_reset, - .assert = ox820_reset_assert, - .deassert = ox820_reset_deassert, -}; - -static const struct of_device_id ox820_reset_dt_ids[] = { - { .compatible = "plxtech,nas782x-reset", }, - { /* sentinel */ }, -}; -MODULE_DEVICE_TABLE(of, ox820_reset_dt_ids); - -struct reset_controller_dev rcdev; - -static int ox820_reset_probe(struct platform_device *pdev) -{ - struct reset_controller_dev *rcdev; - - rcdev = devm_kzalloc(&pdev->dev, sizeof(*rcdev), GFP_KERNEL); - if (!rcdev) - return -ENOMEM; - - /* note: reset controller is statically mapped */ - - rcdev->owner = THIS_MODULE; - rcdev->nr_resets = 32; - rcdev->ops = &ox820_reset_ops; - rcdev->of_node = pdev->dev.of_node; - reset_controller_register(rcdev); - platform_set_drvdata(pdev, rcdev); - - return 0; -} - -static int ox820_reset_remove(struct platform_device *pdev) -{ - struct reset_controller_dev *rcdev = platform_get_drvdata(pdev); - - reset_controller_unregister(rcdev); - - return 0; -} - -static struct platform_driver ox820_reset_driver = { - .probe = ox820_reset_probe, - .remove = ox820_reset_remove, - .driver = { - .name = "ox820-reset", - .owner = THIS_MODULE, - .of_match_table = ox820_reset_dt_ids, - }, -}; - -static int __init ox820_reset_init(void) -{ - return platform_driver_probe(&ox820_reset_driver, - ox820_reset_probe); -} -/* - * reset controller does not support probe deferral, so it has to be - * initialized before any user, in particular, PCIE uses subsys_initcall. - */ -arch_initcall(ox820_reset_init); - -MODULE_AUTHOR("Ma Haijun"); -MODULE_LICENSE("GPL"); diff --git a/target/linux/oxnas/files/drivers/usb/host/ehci-oxnas.c b/target/linux/oxnas/files/drivers/usb/host/ehci-oxnas.c index 15578a3027..79c4fa3a95 100644 --- a/target/linux/oxnas/files/drivers/usb/host/ehci-oxnas.c +++ b/target/linux/oxnas/files/drivers/usb/host/ehci-oxnas.c @@ -14,13 +14,59 @@ #include <linux/of.h> #include <linux/of_address.h> #include <linux/of_irq.h> +#include <linux/mfd/syscon.h> #include <linux/usb.h> #include <linux/usb/hcd.h> #include <linux/dma-mapping.h> #include <linux/clk.h> +#include <linux/regmap.h> #include <linux/reset.h> -#include <mach/hardware.h> -#include <mach/utils.h> + +#define USBHSMPH_CTRL_REGOFFSET 0x40 +#define USBHSMPH_STAT_REGOFFSET 0x44 +#define REF300_DIV_REGOFFSET 0xF8 +#define USBHSPHY_CTRL_REGOFFSET 0x84 +#define USB_CTRL_REGOFFSET 0x90 +#define PLLB_DIV_CTRL_REGOFFSET 0x1000F8 +#define USBHSPHY_SUSPENDM_MANUAL_ENABLE 16 +#define USBHSPHY_SUSPENDM_MANUAL_STATE 15 +#define USBHSPHY_ATE_ESET 14 +#define USBHSPHY_TEST_DIN 6 +#define USBHSPHY_TEST_ADD 2 +#define USBHSPHY_TEST_DOUT_SEL 1 +#define USBHSPHY_TEST_CLK 0 + +#define USB_CTRL_USBAPHY_CKSEL_SHIFT 5 +#define USB_CLK_XTAL0_XTAL1 (0 << USB_CTRL_USBAPHY_CKSEL_SHIFT) +#define USB_CLK_XTAL0 (1 << USB_CTRL_USBAPHY_CKSEL_SHIFT) +#define USB_CLK_INTERNAL (2 << USB_CTRL_USBAPHY_CKSEL_SHIFT) + +#define USBAMUX_DEVICE BIT(4) + +#define USBPHY_REFCLKDIV_SHIFT 2 +#define USB_PHY_REF_12MHZ (0 << USBPHY_REFCLKDIV_SHIFT) +#define USB_PHY_REF_24MHZ (1 << USBPHY_REFCLKDIV_SHIFT) +#define USB_PHY_REF_48MHZ (2 << USBPHY_REFCLKDIV_SHIFT) + +#define USB_CTRL_USB_CKO_SEL_BIT 0 + +#define USB_INT_CLK_XTAL 0 +#define USB_INT_CLK_REF300 2 +#define USB_INT_CLK_PLLB 3 + +#define REF300_DIV_INT_SHIFT 8 +#define REF300_DIV_FRAC_SHIFT 0 +#define REF300_DIV_INT(val) ((val) << REF300_DIV_INT_SHIFT) +#define REF300_DIV_FRAC(val) ((val) << REF300_DIV_FRAC_SHIFT) + +#define PLLB_BYPASS 1 +#define PLLB_ENSAT 3 +#define PLLB_OUTDIV 4 +#define PLLB_REFDIV 8 +#define PLLB_DIV_INT_SHIFT 8 +#define PLLB_DIV_FRAC_SHIFT 0 +#define PLLB_DIV_INT(val) ((val) << PLLB_DIV_INT_SHIFT) +#define PLLB_DIV_FRAC(val) ((val) << PLLB_DIV_FRAC_SHIFT) #include "ehci.h" @@ -33,6 +79,7 @@ struct oxnas_hcd { struct reset_control *rst_host; struct reset_control *rst_phya; struct reset_control *rst_phyb; + struct regmap *syscon; }; #define DRIVER_DESC "Oxnas On-Chip EHCI Host Controller" @@ -41,21 +88,16 @@ static struct hc_driver __read_mostly oxnas_hc_driver; static void start_oxnas_usb_ehci(struct oxnas_hcd *oxnas) { - u32 reg; - if (oxnas->use_pllb) { /* enable pllb */ clk_prepare_enable(oxnas->refsrc); /* enable ref600 */ clk_prepare_enable(oxnas->phyref); /* 600MHz pllb divider for 12MHz */ - writel(PLLB_DIV_INT(50) | PLLB_DIV_FRAC(0), - SEC_CTRL_PLLB_DIV_CTRL); - + regmap_write_bits(oxnas->syscon, PLLB_DIV_CTRL_REGOFFSET, 0xffff, PLLB_DIV_INT(50) | PLLB_DIV_FRAC(0)); } else { /* ref 300 divider for 12MHz */ - writel(REF300_DIV_INT(25) | REF300_DIV_FRAC(0), - SYS_CTRL_REF300_DIV); + regmap_write_bits(oxnas->syscon, REF300_DIV_REGOFFSET, 0xffff, REF300_DIV_INT(25) | REF300_DIV_FRAC(0)); } /* Ensure the USB block is properly reset */ @@ -65,31 +107,34 @@ static void start_oxnas_usb_ehci(struct oxnas_hcd *oxnas) /* Force the high speed clock to be generated all the time, via serial programming of the USB HS PHY */ - writel((2UL << USBHSPHY_TEST_ADD) | - (0xe0UL << USBHSPHY_TEST_DIN), SYS_CTRL_USBHSPHY_CTRL); + regmap_write_bits(oxnas->syscon, USBHSPHY_CTRL_REGOFFSET, 0xffff, + (2UL << USBHSPHY_TEST_ADD) | + (0xe0UL << USBHSPHY_TEST_DIN)); - writel((1UL << USBHSPHY_TEST_CLK) | - (2UL << USBHSPHY_TEST_ADD) | - (0xe0UL << USBHSPHY_TEST_DIN), SYS_CTRL_USBHSPHY_CTRL); + regmap_write_bits(oxnas->syscon, USBHSPHY_CTRL_REGOFFSET, 0xffff, + (1UL << USBHSPHY_TEST_CLK) | + (2UL << USBHSPHY_TEST_ADD) | + (0xe0UL << USBHSPHY_TEST_DIN)); - writel((0xfUL << USBHSPHY_TEST_ADD) | - (0xaaUL << USBHSPHY_TEST_DIN), SYS_CTRL_USBHSPHY_CTRL); + regmap_write_bits(oxnas->syscon, USBHSPHY_CTRL_REGOFFSET, 0xffff, + (0xfUL << USBHSPHY_TEST_ADD) | + (0xaaUL << USBHSPHY_TEST_DIN)); - writel((1UL << USBHSPHY_TEST_CLK) | - (0xfUL << USBHSPHY_TEST_ADD) | - (0xaaUL << USBHSPHY_TEST_DIN), SYS_CTRL_USBHSPHY_CTRL); + regmap_write_bits(oxnas->syscon, USBHSPHY_CTRL_REGOFFSET, 0xffff, + (1UL << USBHSPHY_TEST_CLK) | + (0xfUL << USBHSPHY_TEST_ADD) | + (0xaaUL << USBHSPHY_TEST_DIN)); if (oxnas->use_pllb) /* use pllb clock */ - writel(USB_CLK_INTERNAL | USB_INT_CLK_PLLB, SYS_CTRL_USB_CTRL); + regmap_write_bits(oxnas->syscon, USB_CTRL_REGOFFSET, 0xffff, + USB_CLK_INTERNAL | USB_INT_CLK_PLLB); else /* use ref300 derived clock */ - writel(USB_CLK_INTERNAL | USB_INT_CLK_REF300, - SYS_CTRL_USB_CTRL); + regmap_write_bits(oxnas->syscon, USB_CTRL_REGOFFSET, 0xffff, + USB_CLK_INTERNAL | USB_INT_CLK_REF300); if (oxnas->use_phya) { /* Configure USB PHYA as a host */ - reg = readl(SYS_CTRL_USB_CTRL); - reg &= ~USBAMUX_DEVICE; - writel(reg, SYS_CTRL_USB_CTRL); + regmap_update_bits(oxnas->syscon, USB_CTRL_REGOFFSET, USBAMUX_DEVICE, 0); } /* Enable the clock to the USB block */ @@ -172,8 +217,14 @@ static int ehci_oxnas_drv_probe(struct platform_device *ofdev) oxnas = (struct oxnas_hcd *)hcd_to_ehci(hcd)->priv; - oxnas->use_pllb = of_property_read_bool(np, "plxtech,ehci_use_pllb"); - oxnas->use_phya = of_property_read_bool(np, "plxtech,ehci_use_phya"); + oxnas->use_pllb = of_property_read_bool(np, "oxsemi,ehci_use_pllb"); + oxnas->use_phya = of_property_read_bool(np, "oxsemi,ehci_use_phya"); + + oxnas->syscon = syscon_regmap_lookup_by_phandle(np, "oxsemi,sys-ctrl"); + if (IS_ERR(oxnas->syscon)) { + err = PTR_ERR(oxnas->syscon); + goto err_syscon; + } oxnas->clk = of_clk_get_by_name(np, "usb"); if (IS_ERR(oxnas->clk)) { @@ -249,6 +300,7 @@ err_phyref: clk_put(oxnas->refsrc); err_refsrc: clk_put(oxnas->clk); +err_syscon: err_clk: err_ioremap: err_res: |