From a13767bc0ee8ccaf4e7f64192e7f1d408dc7f900 Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Thu, 14 Apr 2016 14:15:47 +0200 Subject: [PATCH 001/162] i2c: cdns: Read address from DT in ofdata_to_platdata Extract reading IP base address in function which is designed for it. Also enable option to read more information from DT in this function. Signed-off-by: Michal Simek Reviewed-by: Heiko Schocher --- drivers/i2c/i2c-cdns.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/drivers/i2c/i2c-cdns.c b/drivers/i2c/i2c-cdns.c index 909cea2418..66bd580aad 100644 --- a/drivers/i2c/i2c-cdns.c +++ b/drivers/i2c/i2c-cdns.c @@ -125,10 +125,6 @@ static int cdns_i2c_probe(struct udevice *dev) { struct i2c_cdns_bus *bus = dev_get_priv(dev); - bus->regs = (struct cdns_i2c_regs *)dev_get_addr(dev); - if (!bus->regs) - return -ENOMEM; - /* TODO: Calculate dividers based on CPU_CLK_1X */ /* 111MHz / ( (3 * 17) * 22 ) = ~100KHz */ writel((16 << CDNS_I2C_CONTROL_DIV_B_SHIFT) | @@ -313,6 +309,17 @@ static int cdns_i2c_xfer(struct udevice *dev, struct i2c_msg *msg, return 0; } +static int cdns_i2c_ofdata_to_platdata(struct udevice *dev) +{ + struct i2c_cdns_bus *i2c_bus = dev_get_priv(dev); + + i2c_bus->regs = (struct cdns_i2c_regs *)dev_get_addr(dev); + if (!i2c_bus->regs) + return -ENOMEM; + + return 0; +} + static const struct dm_i2c_ops cdns_i2c_ops = { .xfer = cdns_i2c_xfer, .probe_chip = cdns_i2c_probe_chip, @@ -330,6 +337,7 @@ U_BOOT_DRIVER(cdns_i2c) = { .of_match = cdns_i2c_of_match, .probe = cdns_i2c_probe, .remove = cdns_i2c_remove, + .ofdata_to_platdata = cdns_i2c_ofdata_to_platdata, .priv_auto_alloc_size = sizeof(struct i2c_cdns_bus), .ops = &cdns_i2c_ops, }; From 6150be9094bb155022da3843b56e6314edf54305 Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Thu, 14 Apr 2016 14:15:48 +0200 Subject: [PATCH 002/162] i2c: cdns: Moving speed setup from probe to set_bus_speed function set_bus_speed is the right function where bus speed should be setup. This move enable option to remove probe and remove functions which are empty. Signed-off-by: Michal Simek --- drivers/i2c/i2c-cdns.c | 48 ++++++++++-------------------------------- 1 file changed, 11 insertions(+), 37 deletions(-) diff --git a/drivers/i2c/i2c-cdns.c b/drivers/i2c/i2c-cdns.c index 66bd580aad..0bc6aaaa6f 100644 --- a/drivers/i2c/i2c-cdns.c +++ b/drivers/i2c/i2c-cdns.c @@ -115,41 +115,6 @@ struct i2c_cdns_bus { struct cdns_i2c_regs __iomem *regs; /* register base */ }; - -/** cdns_i2c_probe() - Probe method - * @dev: udevice pointer - * - * DM callback called when device is probed - */ -static int cdns_i2c_probe(struct udevice *dev) -{ - struct i2c_cdns_bus *bus = dev_get_priv(dev); - - /* TODO: Calculate dividers based on CPU_CLK_1X */ - /* 111MHz / ( (3 * 17) * 22 ) = ~100KHz */ - writel((16 << CDNS_I2C_CONTROL_DIV_B_SHIFT) | - (2 << CDNS_I2C_CONTROL_DIV_A_SHIFT), &bus->regs->control); - - /* Enable master mode, ack, and 7-bit addressing */ - setbits_le32(&bus->regs->control, CDNS_I2C_CONTROL_MS | - CDNS_I2C_CONTROL_ACKEN | CDNS_I2C_CONTROL_NEA); - - debug("%s bus %d at %p\n", __func__, dev->seq, bus->regs); - - return 0; -} - -static int cdns_i2c_remove(struct udevice *dev) -{ - struct i2c_cdns_bus *bus = dev_get_priv(dev); - - debug("%s bus %d at %p\n", __func__, dev->seq, bus->regs); - - unmap_sysmem(bus->regs); - - return 0; -} - /* Wait for an interrupt */ static u32 cdns_i2c_wait(struct cdns_i2c_regs *cdns_i2c, u32 mask) { @@ -170,12 +135,23 @@ static u32 cdns_i2c_wait(struct cdns_i2c_regs *cdns_i2c, u32 mask) static int cdns_i2c_set_bus_speed(struct udevice *dev, unsigned int speed) { + struct i2c_cdns_bus *bus = dev_get_priv(dev); + if (speed != 100000) { printf("%s, failed to set clock speed to %u\n", __func__, speed); return -EINVAL; } + /* TODO: Calculate dividers based on CPU_CLK_1X */ + /* 111MHz / ( (3 * 17) * 22 ) = ~100KHz */ + writel((16 << CDNS_I2C_CONTROL_DIV_B_SHIFT) | + (2 << CDNS_I2C_CONTROL_DIV_A_SHIFT), &bus->regs->control); + + /* Enable master mode, ack, and 7-bit addressing */ + setbits_le32(&bus->regs->control, CDNS_I2C_CONTROL_MS | + CDNS_I2C_CONTROL_ACKEN | CDNS_I2C_CONTROL_NEA); + return 0; } @@ -335,8 +311,6 @@ U_BOOT_DRIVER(cdns_i2c) = { .name = "i2c-cdns", .id = UCLASS_I2C, .of_match = cdns_i2c_of_match, - .probe = cdns_i2c_probe, - .remove = cdns_i2c_remove, .ofdata_to_platdata = cdns_i2c_ofdata_to_platdata, .priv_auto_alloc_size = sizeof(struct i2c_cdns_bus), .ops = &cdns_i2c_ops, From ad72e7622bd587dc798fbac0351b558fb18caa97 Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Thu, 14 Apr 2016 14:15:49 +0200 Subject: [PATCH 003/162] i2c: cdns: Support different bus speeds 400kHz is maximum freq which can be used on Xilinx ZynqMP. Support it with standard divider calculator. Input freq is hardcoded to 100MHz input freq till we have clock driver which can provide this information for exact configuration. Signed-off-by: Michal Simek Reviewed-by: Heiko Schocher --- drivers/i2c/i2c-cdns.c | 76 ++++++++++++++++++++++++++++++++++++++---- 1 file changed, 69 insertions(+), 7 deletions(-) diff --git a/drivers/i2c/i2c-cdns.c b/drivers/i2c/i2c-cdns.c index 0bc6aaaa6f..5642cd91fe 100644 --- a/drivers/i2c/i2c-cdns.c +++ b/drivers/i2c/i2c-cdns.c @@ -112,6 +112,7 @@ static void cdns_i2c_debug_status(struct cdns_i2c_regs *cdns_i2c) struct i2c_cdns_bus { int id; + unsigned int input_freq; struct cdns_i2c_regs __iomem *regs; /* register base */ }; @@ -133,20 +134,79 @@ static u32 cdns_i2c_wait(struct cdns_i2c_regs *cdns_i2c, u32 mask) return int_status & mask; } +#define CDNS_I2C_DIVA_MAX 4 +#define CDNS_I2C_DIVB_MAX 64 + +static int cdns_i2c_calc_divs(unsigned long *f, unsigned long input_clk, + unsigned int *a, unsigned int *b) +{ + unsigned long fscl = *f, best_fscl = *f, actual_fscl, temp; + unsigned int div_a, div_b, calc_div_a = 0, calc_div_b = 0; + unsigned int last_error, current_error; + + /* calculate (divisor_a+1) x (divisor_b+1) */ + temp = input_clk / (22 * fscl); + + /* + * If the calculated value is negative or 0CDNS_I2C_DIVA_MAX, + * the fscl input is out of range. Return error. + */ + if (!temp || (temp > (CDNS_I2C_DIVA_MAX * CDNS_I2C_DIVB_MAX))) + return -EINVAL; + + last_error = -1; + for (div_a = 0; div_a < CDNS_I2C_DIVA_MAX; div_a++) { + div_b = DIV_ROUND_UP(input_clk, 22 * fscl * (div_a + 1)); + + if ((div_b < 1) || (div_b > CDNS_I2C_DIVB_MAX)) + continue; + div_b--; + + actual_fscl = input_clk / (22 * (div_a + 1) * (div_b + 1)); + + if (actual_fscl > fscl) + continue; + + current_error = ((actual_fscl > fscl) ? (actual_fscl - fscl) : + (fscl - actual_fscl)); + + if (last_error > current_error) { + calc_div_a = div_a; + calc_div_b = div_b; + best_fscl = actual_fscl; + last_error = current_error; + } + } + + *a = calc_div_a; + *b = calc_div_b; + *f = best_fscl; + + return 0; +} + static int cdns_i2c_set_bus_speed(struct udevice *dev, unsigned int speed) { struct i2c_cdns_bus *bus = dev_get_priv(dev); + u32 div_a = 0, div_b = 0; + unsigned long speed_p = speed; + int ret = 0; - if (speed != 100000) { - printf("%s, failed to set clock speed to %u\n", __func__, - speed); + if (speed > 400000) { + debug("%s, failed to set clock speed to %u\n", __func__, + speed); return -EINVAL; } - /* TODO: Calculate dividers based on CPU_CLK_1X */ - /* 111MHz / ( (3 * 17) * 22 ) = ~100KHz */ - writel((16 << CDNS_I2C_CONTROL_DIV_B_SHIFT) | - (2 << CDNS_I2C_CONTROL_DIV_A_SHIFT), &bus->regs->control); + ret = cdns_i2c_calc_divs(&speed_p, bus->input_freq, &div_a, &div_b); + if (ret) + return ret; + + debug("%s: div_a: %d, div_b: %d, input freq: %d, speed: %d/%ld\n", + __func__, div_a, div_b, bus->input_freq, speed, speed_p); + + writel((div_b << CDNS_I2C_CONTROL_DIV_B_SHIFT) | + (div_a << CDNS_I2C_CONTROL_DIV_A_SHIFT), &bus->regs->control); /* Enable master mode, ack, and 7-bit addressing */ setbits_le32(&bus->regs->control, CDNS_I2C_CONTROL_MS | @@ -293,6 +353,8 @@ static int cdns_i2c_ofdata_to_platdata(struct udevice *dev) if (!i2c_bus->regs) return -ENOMEM; + i2c_bus->input_freq = 100000000; /* TODO hardcode input freq for now */ + return 0; } From d79ac324789839b4b10b37e2ff64dd9e4a92441e Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Mon, 25 Apr 2016 10:50:42 +0200 Subject: [PATCH 004/162] i2c: muxes: Add support for TI PCA954X mux Add support for common TI i2c mux which is available on ZynqMP zcu102 board. DM i2c mux core code is selecting/deselecting bus before/after every command is performed that's why only one channel is active at a time. That's also the reason why deselect is just disable all available channels. Signed-off-by: Michal Simek Reviewed-by: Heiko Schocher Reviewed-by: Simon Glass --- drivers/i2c/muxes/Kconfig | 10 +++++ drivers/i2c/muxes/Makefile | 1 + drivers/i2c/muxes/pca954x.c | 79 +++++++++++++++++++++++++++++++++++++ 3 files changed, 90 insertions(+) create mode 100644 drivers/i2c/muxes/pca954x.c diff --git a/drivers/i2c/muxes/Kconfig b/drivers/i2c/muxes/Kconfig index f959d9de9e..48900ed2af 100644 --- a/drivers/i2c/muxes/Kconfig +++ b/drivers/i2c/muxes/Kconfig @@ -24,3 +24,13 @@ config I2C_ARB_GPIO_CHALLENGE I2C multimaster arbitration scheme using GPIOs and a challenge & response mechanism where masters have to claim the bus by asserting a GPIO. + +config I2C_MUX_PCA954x + tristate "TI PCA954x I2C Mux/switches" + depends on I2C_MUX + help + If you say yes here you get support for the TI PCA954x + I2C mux/switch devices. It is x width I2C multiplexer which enables to + paritioning I2C bus and connect multiple devices with the same address + to the same I2C controller where driver handles proper routing to + target i2c device. PCA9544 and PCA9548 are supported. diff --git a/drivers/i2c/muxes/Makefile b/drivers/i2c/muxes/Makefile index 47c1240d7e..0811add421 100644 --- a/drivers/i2c/muxes/Makefile +++ b/drivers/i2c/muxes/Makefile @@ -5,3 +5,4 @@ # obj-$(CONFIG_I2C_ARB_GPIO_CHALLENGE) += i2c-arb-gpio-challenge.o obj-$(CONFIG_$(SPL_)I2C_MUX) += i2c-mux-uclass.o +obj-$(CONFIG_I2C_MUX_PCA954x) += pca954x.o diff --git a/drivers/i2c/muxes/pca954x.c b/drivers/i2c/muxes/pca954x.c new file mode 100644 index 0000000000..7e0d2da4d6 --- /dev/null +++ b/drivers/i2c/muxes/pca954x.c @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2015 - 2016 Xilinx, Inc. + * Written by Michal Simek + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include +#include + +DECLARE_GLOBAL_DATA_PTR; + +struct pca954x_priv { + u32 addr; /* I2C mux address */ + u32 width; /* I2C mux width - number of busses */ +}; + +static int pca954x_deselect(struct udevice *mux, struct udevice *bus, + uint channel) +{ + struct pca954x_priv *priv = dev_get_priv(mux); + uchar byte = 0; + + return dm_i2c_write(mux, priv->addr, &byte, 1); +} + +static int pca954x_select(struct udevice *mux, struct udevice *bus, + uint channel) +{ + struct pca954x_priv *priv = dev_get_priv(mux); + uchar byte = 1 << channel; + + return dm_i2c_write(mux, priv->addr, &byte, 1); +} + +static const struct i2c_mux_ops pca954x_ops = { + .select = pca954x_select, + .deselect = pca954x_deselect, +}; + +static const struct udevice_id pca954x_ids[] = { + { .compatible = "nxp,pca9548", .data = (ulong)8 }, + { .compatible = "nxp,pca9544", .data = (ulong)4 }, + { } +}; + +static int pca954x_ofdata_to_platdata(struct udevice *dev) +{ + struct pca954x_priv *priv = dev_get_priv(dev); + + priv->addr = fdtdec_get_int(gd->fdt_blob, dev->of_offset, "reg", 0); + if (!priv->addr) { + debug("MUX not found\n"); + return -ENODEV; + } + priv->width = dev_get_driver_data(dev); + + if (!priv->width) { + debug("No I2C MUX width specified\n"); + return -EINVAL; + } + + debug("Device %s at 0x%x with width %d\n", + dev->name, priv->addr, priv->width); + + return 0; +} + +U_BOOT_DRIVER(pca954x) = { + .name = "pca954x", + .id = UCLASS_I2C_MUX, + .of_match = pca954x_ids, + .ops = &pca954x_ops, + .ofdata_to_platdata = pca954x_ofdata_to_platdata, + .priv_auto_alloc_size = sizeof(struct pca954x_priv), +}; From b6a77b0ce8ac21c154f02907c364b6d3e3c8af5e Mon Sep 17 00:00:00 2001 From: Stefan Roese Date: Wed, 27 Apr 2016 09:02:12 +0200 Subject: [PATCH 005/162] i2c: designware_i2c: Optionally check enable status register Some platforms don't implement the enable status register at offset 0x9c. The SPEAr600 platform is one of them. The recently added check to this status register can't be performend on these platforms. This patch introduces a new config option that can be enabled on such platforms not supporting this register. Signed-off-by: Stefan Roese Cc: Heiko Schocher Reviewed-by: Heiko Schocher --- drivers/i2c/designware_i2c.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/i2c/designware_i2c.c b/drivers/i2c/designware_i2c.c index 0c7cd0ba72..e60fd0a419 100644 --- a/drivers/i2c/designware_i2c.c +++ b/drivers/i2c/designware_i2c.c @@ -36,6 +36,14 @@ struct dw_i2c { struct dw_scl_sda_cfg *scl_sda_cfg; }; +#ifdef CONFIG_SYS_I2C_DW_ENABLE_STATUS_UNSUPPORTED +static void dw_i2c_enable(struct i2c_regs *i2c_base, bool enable) +{ + u32 ena = enable ? IC_ENABLE_0B : 0; + + writel(ena, &i2c_base->ic_enable); +} +#else static void dw_i2c_enable(struct i2c_regs *i2c_base, bool enable) { u32 ena = enable ? IC_ENABLE_0B : 0; @@ -56,6 +64,7 @@ static void dw_i2c_enable(struct i2c_regs *i2c_base, bool enable) printf("timeout in %sabling I2C adapter\n", enable ? "en" : "dis"); } +#endif /* * i2c_set_bus_speed - Set the i2c speed From ec2c81c5d4681274f9f9d079b08ed259ff20dc69 Mon Sep 17 00:00:00 2001 From: "mario.six@gdsys.cc" Date: Mon, 25 Apr 2016 08:31:01 +0200 Subject: [PATCH 006/162] dm: fsl_i2c: Rename I2C register structure Signed-off-by: Mario Six --- arch/m68k/include/asm/fsl_i2c.h | 2 +- arch/powerpc/include/asm/fsl_i2c.h | 2 +- arch/powerpc/include/asm/immap_85xx.h | 4 +- arch/powerpc/include/asm/immap_86xx.h | 4 +- board/keymile/km83xx/km83xx_i2c.c | 28 +++--- drivers/i2c/fsl_i2c.c | 123 ++++++++++++++------------ 6 files changed, 87 insertions(+), 76 deletions(-) diff --git a/arch/m68k/include/asm/fsl_i2c.h b/arch/m68k/include/asm/fsl_i2c.h index 1b1c25ef89..c7d2aa33e8 100644 --- a/arch/m68k/include/asm/fsl_i2c.h +++ b/arch/m68k/include/asm/fsl_i2c.h @@ -16,7 +16,7 @@ #include -typedef struct fsl_i2c { +typedef struct fsl_i2c_base { u8 adr; /* I2C slave address */ u8 res0[3]; diff --git a/arch/powerpc/include/asm/fsl_i2c.h b/arch/powerpc/include/asm/fsl_i2c.h index cbbc834273..e94bdc690e 100644 --- a/arch/powerpc/include/asm/fsl_i2c.h +++ b/arch/powerpc/include/asm/fsl_i2c.h @@ -16,7 +16,7 @@ #include -typedef struct fsl_i2c { +typedef struct fsl_i2c_base { u8 adr; /* I2C slave address */ u8 res0[3]; diff --git a/arch/powerpc/include/asm/immap_85xx.h b/arch/powerpc/include/asm/immap_85xx.h index 53ca6d94d6..07d2adf71f 100644 --- a/arch/powerpc/include/asm/immap_85xx.h +++ b/arch/powerpc/include/asm/immap_85xx.h @@ -120,8 +120,8 @@ typedef struct ccsr_local_ecm { /* I2C Registers */ typedef struct ccsr_i2c { - struct fsl_i2c i2c[1]; - u8 res[4096 - 1 * sizeof(struct fsl_i2c)]; + struct fsl_i2c_base i2c[1]; + u8 res[4096 - 1 * sizeof(struct fsl_i2c_base)]; } ccsr_i2c_t; #if defined(CONFIG_MPC8540) \ diff --git a/arch/powerpc/include/asm/immap_86xx.h b/arch/powerpc/include/asm/immap_86xx.h index 177918b7f9..b078569c45 100644 --- a/arch/powerpc/include/asm/immap_86xx.h +++ b/arch/powerpc/include/asm/immap_86xx.h @@ -92,8 +92,8 @@ typedef struct ccsr_local_mcm { /* Daul I2C Registers(0x3000-0x4000) */ typedef struct ccsr_i2c { - struct fsl_i2c i2c[2]; - u8 res[4096 - 2 * sizeof(struct fsl_i2c)]; + struct fsl_i2c_base i2c[2]; + u8 res[4096 - 2 * sizeof(struct fsl_i2c_base)]; } ccsr_i2c_t; /* DUART Registers(0x4000-0x5000) */ diff --git a/board/keymile/km83xx/km83xx_i2c.c b/board/keymile/km83xx/km83xx_i2c.c index c961937530..f0b528d1c8 100644 --- a/board/keymile/km83xx/km83xx_i2c.c +++ b/board/keymile/km83xx/km83xx_i2c.c @@ -13,31 +13,33 @@ static void i2c_write_start_seq(void) { - struct fsl_i2c *dev; - dev = (struct fsl_i2c *) (CONFIG_SYS_IMMR + CONFIG_SYS_I2C_OFFSET); + struct fsl_i2c_base *base; + base = (struct fsl_i2c_base *)(CONFIG_SYS_IMMR + + CONFIG_SYS_I2C_OFFSET); udelay(DELAY_ABORT_SEQ); - out_8(&dev->cr, (I2C_CR_MEN | I2C_CR_MSTA)); + out_8(&base->cr, (I2C_CR_MEN | I2C_CR_MSTA)); udelay(DELAY_ABORT_SEQ); - out_8(&dev->cr, (I2C_CR_MEN)); + out_8(&base->cr, (I2C_CR_MEN)); } int i2c_make_abort(void) { - struct fsl_i2c *dev; - dev = (struct fsl_i2c *) (CONFIG_SYS_IMMR + CONFIG_SYS_I2C_OFFSET); + struct fsl_i2c_base *base; + base = (struct fsl_i2c_base *)(CONFIG_SYS_IMMR + + CONFIG_SYS_I2C_OFFSET); uchar last; int nbr_read = 0; int i = 0; int ret = 0; /* wait after each operation to finsh with a delay */ - out_8(&dev->cr, (I2C_CR_MSTA)); + out_8(&base->cr, (I2C_CR_MSTA)); udelay(DELAY_ABORT_SEQ); - out_8(&dev->cr, (I2C_CR_MEN | I2C_CR_MSTA)); + out_8(&base->cr, (I2C_CR_MEN | I2C_CR_MSTA)); udelay(DELAY_ABORT_SEQ); - in_8(&dev->dr); + in_8(&base->dr); udelay(DELAY_ABORT_SEQ); - last = in_8(&dev->dr); + last = in_8(&base->dr); nbr_read++; /* @@ -47,7 +49,7 @@ int i2c_make_abort(void) while (((last & 0x01) != 0x01) && (nbr_read < CONFIG_SYS_IVM_EEPROM_MAX_LEN)) { udelay(DELAY_ABORT_SEQ); - last = in_8(&dev->dr); + last = in_8(&base->dr); nbr_read++; } if ((last & 0x01) != 0x01) @@ -56,10 +58,10 @@ int i2c_make_abort(void) printf("[INFO] i2c abort after %d bytes (0x%02x)\n", nbr_read, last); udelay(DELAY_ABORT_SEQ); - out_8(&dev->cr, (I2C_CR_MEN)); + out_8(&base->cr, (I2C_CR_MEN)); udelay(DELAY_ABORT_SEQ); /* clear status reg */ - out_8(&dev->sr, 0); + out_8(&base->sr, 0); for (i = 0; i < 5; i++) i2c_write_start_seq(); diff --git a/drivers/i2c/fsl_i2c.c b/drivers/i2c/fsl_i2c.c index b56a1c2541..70c7cbab57 100644 --- a/drivers/i2c/fsl_i2c.c +++ b/drivers/i2c/fsl_i2c.c @@ -34,16 +34,16 @@ DECLARE_GLOBAL_DATA_PTR; -static const struct fsl_i2c *i2c_dev[4] = { - (struct fsl_i2c *)(CONFIG_SYS_IMMR + CONFIG_SYS_FSL_I2C_OFFSET), +static const struct fsl_i2c_base *i2c_base[4] = { + (struct fsl_i2c_base *)(CONFIG_SYS_IMMR + CONFIG_SYS_FSL_I2C_OFFSET), #ifdef CONFIG_SYS_FSL_I2C2_OFFSET - (struct fsl_i2c *)(CONFIG_SYS_IMMR + CONFIG_SYS_FSL_I2C2_OFFSET), + (struct fsl_i2c_base *)(CONFIG_SYS_IMMR + CONFIG_SYS_FSL_I2C2_OFFSET), #endif #ifdef CONFIG_SYS_FSL_I2C3_OFFSET - (struct fsl_i2c *)(CONFIG_SYS_IMMR + CONFIG_SYS_FSL_I2C3_OFFSET), + (struct fsl_i2c_base *)(CONFIG_SYS_IMMR + CONFIG_SYS_FSL_I2C3_OFFSET), #endif #ifdef CONFIG_SYS_FSL_I2C4_OFFSET - (struct fsl_i2c *)(CONFIG_SYS_IMMR + CONFIG_SYS_FSL_I2C4_OFFSET) + (struct fsl_i2c_base *)(CONFIG_SYS_IMMR + CONFIG_SYS_FSL_I2C4_OFFSET) #endif }; @@ -104,7 +104,7 @@ static const struct { /** * Set the I2C bus speed for a given I2C device * - * @param dev: the I2C device + * @param base: the I2C device registers * @i2c_clk: I2C bus clock frequency * @speed: the desired speed of the bus * @@ -112,7 +112,7 @@ static const struct { * * The return value is the actual bus speed that is set. */ -static unsigned int set_i2c_bus_speed(const struct fsl_i2c *dev, +static unsigned int set_i2c_bus_speed(const struct fsl_i2c_base *base, unsigned int i2c_clk, unsigned int speed) { unsigned short divider = min(i2c_clk / speed, (unsigned int)USHRT_MAX); @@ -173,8 +173,8 @@ static unsigned int set_i2c_bus_speed(const struct fsl_i2c *dev, debug("divider:%d, est_div:%ld, DFSR:%d\n", divider, est_div, dfsr); debug("FDR:0x%.2x, speed:%d\n", fdr, speed); #endif - writeb(dfsr, &dev->dfsrr); /* set default filter */ - writeb(fdr, &dev->fdr); /* set bus speed */ + writeb(dfsr, &base->dfsrr); /* set default filter */ + writeb(fdr, &base->fdr); /* set bus speed */ #else unsigned int i; @@ -184,7 +184,7 @@ static unsigned int set_i2c_bus_speed(const struct fsl_i2c *dev, fdr = fsl_i2c_speed_map[i].fdr; speed = i2c_clk / fsl_i2c_speed_map[i].divider; - writeb(fdr, &dev->fdr); /* set bus speed */ + writeb(fdr, &base->fdr); /* set bus speed */ break; } @@ -200,7 +200,7 @@ static unsigned int get_i2c_clock(int bus) return gd->arch.i2c1_clk; /* I2C1 clock */ } -static int fsl_i2c_fixup(const struct fsl_i2c *dev) +static int fsl_i2c_fixup(const struct fsl_i2c_base *base) { const unsigned long long timeout = usec2ticks(CONFIG_I2C_MBB_TIMEOUT); unsigned long long timeval = 0; @@ -214,34 +214,34 @@ static int fsl_i2c_fixup(const struct fsl_i2c *dev) flags = I2C_CR_BIT6; #endif - writeb(I2C_CR_MEN | I2C_CR_MSTA, &dev->cr); + writeb(I2C_CR_MEN | I2C_CR_MSTA, &base->cr); timeval = get_ticks(); - while (!(readb(&dev->sr) & I2C_SR_MBB)) { + while (!(readb(&base->sr) & I2C_SR_MBB)) { if ((get_ticks() - timeval) > timeout) goto err; } - if (readb(&dev->sr) & I2C_SR_MAL) { + if (readb(&base->sr) & I2C_SR_MAL) { /* SDA is stuck low */ - writeb(0, &dev->cr); + writeb(0, &base->cr); udelay(100); - writeb(I2C_CR_MSTA | flags, &dev->cr); - writeb(I2C_CR_MEN | I2C_CR_MSTA | flags, &dev->cr); + writeb(I2C_CR_MSTA | flags, &base->cr); + writeb(I2C_CR_MEN | I2C_CR_MSTA | flags, &base->cr); } - readb(&dev->dr); + readb(&base->dr); timeval = get_ticks(); - while (!(readb(&dev->sr) & I2C_SR_MIF)) { + while (!(readb(&base->sr) & I2C_SR_MIF)) { if ((get_ticks() - timeval) > timeout) goto err; } ret = 0; err: - writeb(I2C_CR_MEN | flags, &dev->cr); - writeb(0, &dev->sr); + writeb(I2C_CR_MEN | flags, &base->cr); + writeb(0, &base->sr); udelay(100); return ret; @@ -249,7 +249,7 @@ err: static void fsl_i2c_init(struct i2c_adapter *adap, int speed, int slaveadd) { - const struct fsl_i2c *dev; + const struct fsl_i2c_base *base; const unsigned long long timeout = usec2ticks(CONFIG_I2C_MBB_TIMEOUT); unsigned long long timeval; @@ -260,21 +260,21 @@ static void fsl_i2c_init(struct i2c_adapter *adap, int speed, int slaveadd) */ i2c_init_board(); #endif - dev = (struct fsl_i2c *)i2c_dev[adap->hwadapnr]; + base = (struct fsl_i2c_base *)i2c_base[adap->hwadapnr]; - writeb(0, &dev->cr); /* stop I2C controller */ + writeb(0, &base->cr); /* stop I2C controller */ udelay(5); /* let it shutdown in peace */ - set_i2c_bus_speed(dev, get_i2c_clock(adap->hwadapnr), speed); - writeb(slaveadd << 1, &dev->adr);/* write slave address */ - writeb(0x0, &dev->sr); /* clear status register */ - writeb(I2C_CR_MEN, &dev->cr); /* start I2C controller */ + set_i2c_bus_speed(base, get_i2c_clock(adap->hwadapnr), speed); + writeb(slaveadd << 1, &base->adr);/* write slave address */ + writeb(0x0, &base->sr); /* clear status register */ + writeb(I2C_CR_MEN, &base->cr); /* start I2C controller */ timeval = get_ticks(); - while (readb(&dev->sr) & I2C_SR_MBB) { + while (readb(&base->sr) & I2C_SR_MBB) { if ((get_ticks() - timeval) < timeout) continue; - if (fsl_i2c_fixup(dev)) + if (fsl_i2c_fixup(base)) debug("i2c_init: BUS#%d failed to init\n", adap->hwadapnr); @@ -294,11 +294,12 @@ static void fsl_i2c_init(struct i2c_adapter *adap, int speed, int slaveadd) static int i2c_wait4bus(struct i2c_adapter *adap) { - struct fsl_i2c *dev = (struct fsl_i2c *)i2c_dev[adap->hwadapnr]; + struct fsl_i2c_base *base = + (struct fsl_i2c_base *)i2c_base[adap->hwadapnr]; unsigned long long timeval = get_ticks(); const unsigned long long timeout = usec2ticks(CONFIG_I2C_MBB_TIMEOUT); - while (readb(&dev->sr) & I2C_SR_MBB) { + while (readb(&base->sr) & I2C_SR_MBB) { if ((get_ticks() - timeval) > timeout) return -1; } @@ -312,16 +313,17 @@ i2c_wait(struct i2c_adapter *adap, int write) u32 csr; unsigned long long timeval = get_ticks(); const unsigned long long timeout = usec2ticks(CONFIG_I2C_TIMEOUT); - struct fsl_i2c *dev = (struct fsl_i2c *)i2c_dev[adap->hwadapnr]; + struct fsl_i2c_base *base = + (struct fsl_i2c_base *)i2c_base[adap->hwadapnr]; do { - csr = readb(&dev->sr); + csr = readb(&base->sr); if (!(csr & I2C_SR_MIF)) continue; /* Read again to allow register to stabilise */ - csr = readb(&dev->sr); + csr = readb(&base->sr); - writeb(0x0, &dev->sr); + writeb(0x0, &base->sr); if (csr & I2C_SR_MAL) { debug("i2c_wait: MAL\n"); @@ -348,13 +350,14 @@ i2c_wait(struct i2c_adapter *adap, int write) static __inline__ int i2c_write_addr(struct i2c_adapter *adap, u8 dev, u8 dir, int rsta) { - struct fsl_i2c *device = (struct fsl_i2c *)i2c_dev[adap->hwadapnr]; + struct fsl_i2c_base *base = + (struct fsl_i2c_base *)i2c_base[adap->hwadapnr]; writeb(I2C_CR_MEN | I2C_CR_MSTA | I2C_CR_MTX | (rsta ? I2C_CR_RSTA : 0), - &device->cr); + &base->cr); - writeb((dev << 1) | dir, &device->dr); + writeb((dev << 1) | dir, &base->dr); if (i2c_wait(adap, I2C_WRITE_BIT) < 0) return 0; @@ -365,11 +368,12 @@ i2c_write_addr(struct i2c_adapter *adap, u8 dev, u8 dir, int rsta) static __inline__ int __i2c_write(struct i2c_adapter *adap, u8 *data, int length) { - struct fsl_i2c *dev = (struct fsl_i2c *)i2c_dev[adap->hwadapnr]; + struct fsl_i2c_base *base = + (struct fsl_i2c_base *)i2c_base[adap->hwadapnr]; int i; for (i = 0; i < length; i++) { - writeb(data[i], &dev->dr); + writeb(data[i], &base->dr); if (i2c_wait(adap, I2C_WRITE_BIT) < 0) break; @@ -381,14 +385,15 @@ __i2c_write(struct i2c_adapter *adap, u8 *data, int length) static __inline__ int __i2c_read(struct i2c_adapter *adap, u8 *data, int length) { - struct fsl_i2c *dev = (struct fsl_i2c *)i2c_dev[adap->hwadapnr]; + struct fsl_i2c_base *base = + (struct fsl_i2c_base *)i2c_base[adap->hwadapnr]; int i; writeb(I2C_CR_MEN | I2C_CR_MSTA | ((length == 1) ? I2C_CR_TXAK : 0), - &dev->cr); + &base->cr); /* dummy read */ - readb(&dev->dr); + readb(&base->dr); for (i = 0; i < length; i++) { if (i2c_wait(adap, I2C_READ_BIT) < 0) @@ -397,14 +402,14 @@ __i2c_read(struct i2c_adapter *adap, u8 *data, int length) /* Generate ack on last next to last byte */ if (i == length - 2) writeb(I2C_CR_MEN | I2C_CR_MSTA | I2C_CR_TXAK, - &dev->cr); + &base->cr); /* Do not generate stop on last byte */ if (i == length - 1) writeb(I2C_CR_MEN | I2C_CR_MSTA | I2C_CR_MTX, - &dev->cr); + &base->cr); - data[i] = readb(&dev->dr); + data[i] = readb(&base->dr); } return i; @@ -414,7 +419,8 @@ static int fsl_i2c_read(struct i2c_adapter *adap, u8 dev, uint addr, int alen, u8 *data, int length) { - struct fsl_i2c *device = (struct fsl_i2c *)i2c_dev[adap->hwadapnr]; + struct fsl_i2c_base *base = + (struct fsl_i2c_base *)i2c_base[adap->hwadapnr]; int i = -1; /* signal error */ u8 *a = (u8*)&addr; int len = alen * -1; @@ -457,7 +463,7 @@ fsl_i2c_read(struct i2c_adapter *adap, u8 dev, uint addr, int alen, u8 *data, i = __i2c_read(adap, data, length); } - writeb(I2C_CR_MEN, &device->cr); + writeb(I2C_CR_MEN, &base->cr); if (i2c_wait4bus(adap)) /* Wait until STOP */ debug("i2c_read: wait4bus timed out\n"); @@ -472,7 +478,8 @@ static int fsl_i2c_write(struct i2c_adapter *adap, u8 dev, uint addr, int alen, u8 *data, int length) { - struct fsl_i2c *device = (struct fsl_i2c *)i2c_dev[adap->hwadapnr]; + struct fsl_i2c_base *base = + (struct fsl_i2c_base *)i2c_base[adap->hwadapnr]; int i = -1; /* signal error */ u8 *a = (u8*)&addr; @@ -484,7 +491,7 @@ fsl_i2c_write(struct i2c_adapter *adap, u8 dev, uint addr, int alen, i = __i2c_write(adap, data, length); } - writeb(I2C_CR_MEN, &device->cr); + writeb(I2C_CR_MEN, &base->cr); if (i2c_wait4bus(adap)) /* Wait until STOP */ debug("i2c_write: wait4bus timed out\n"); @@ -497,12 +504,13 @@ fsl_i2c_write(struct i2c_adapter *adap, u8 dev, uint addr, int alen, static int fsl_i2c_probe(struct i2c_adapter *adap, uchar chip) { - struct fsl_i2c *dev = (struct fsl_i2c *)i2c_dev[adap->hwadapnr]; + struct fsl_i2c_base *base = + (struct fsl_i2c_base *)i2c_base[adap->hwadapnr]; /* For unknow reason the controller will ACK when * probing for a slave with the same address, so skip * it. */ - if (chip == (readb(&dev->adr) >> 1)) + if (chip == (readb(&base->adr) >> 1)) return -1; return fsl_i2c_read(adap, chip, 0, 0, NULL, 0); @@ -511,11 +519,12 @@ fsl_i2c_probe(struct i2c_adapter *adap, uchar chip) static unsigned int fsl_i2c_set_bus_speed(struct i2c_adapter *adap, unsigned int speed) { - struct fsl_i2c *dev = (struct fsl_i2c *)i2c_dev[adap->hwadapnr]; + struct fsl_i2c_base *base = + (struct fsl_i2c_base *)i2c_base[adap->hwadapnr]; - writeb(0, &dev->cr); /* stop controller */ - set_i2c_bus_speed(dev, get_i2c_clock(adap->hwadapnr), speed); - writeb(I2C_CR_MEN, &dev->cr); /* start controller */ + writeb(0, &base->cr); /* stop controller */ + set_i2c_bus_speed(base, get_i2c_clock(adap->hwadapnr), speed); + writeb(I2C_CR_MEN, &base->cr); /* start controller */ return 0; } From 2b21e960348998fbaefc802613c37bfb6321969b Mon Sep 17 00:00:00 2001 From: "mario.six@gdsys.cc" Date: Mon, 25 Apr 2016 08:31:02 +0200 Subject: [PATCH 007/162] dm: fsl_i2c: Use clearer parameter names Signed-off-by: Mario Six --- drivers/i2c/fsl_i2c.c | 61 ++++++++++++++++++++++--------------------- 1 file changed, 31 insertions(+), 30 deletions(-) diff --git a/drivers/i2c/fsl_i2c.c b/drivers/i2c/fsl_i2c.c index 70c7cbab57..b0e65fcf65 100644 --- a/drivers/i2c/fsl_i2c.c +++ b/drivers/i2c/fsl_i2c.c @@ -416,24 +416,24 @@ __i2c_read(struct i2c_adapter *adap, u8 *data, int length) } static int -fsl_i2c_read(struct i2c_adapter *adap, u8 dev, uint addr, int alen, u8 *data, - int length) +fsl_i2c_read(struct i2c_adapter *adap, u8 chip_addr, uint offset, int olen, + u8 *data, int dlen) { struct fsl_i2c_base *base = (struct fsl_i2c_base *)i2c_base[adap->hwadapnr]; - int i = -1; /* signal error */ - u8 *a = (u8*)&addr; - int len = alen * -1; + int ret = -1; /* signal error */ + u8 *o = (u8 *)&offset; + int len = olen * -1; if (i2c_wait4bus(adap) < 0) return -1; /* To handle the need of I2C devices that require to write few bytes * (more than 4 bytes of address as in the case of else part) - * of data before reading, Negative equivalent of length(bytes to write) + * of data before reading, Negative equivalent of dlen(bytes to write) * is passed, but used the +ve part of len for writing data */ - if (alen < 0) { + if (olen < 0) { /* Generate a START and send the Address and * the Tx Bytes to the slave. * "START: Address: Write bytes data[len]" @@ -444,23 +444,24 @@ fsl_i2c_read(struct i2c_adapter *adap, u8 dev, uint addr, int alen, u8 *data, * "data", which will eventually keep the data READ, * after writing the len bytes out of it */ - if (i2c_write_addr(adap, dev, I2C_WRITE_BIT, 0) != 0) - i = __i2c_write(adap, data, len); + if (i2c_write_addr(adap, chip_addr, I2C_WRITE_BIT, 0) != 0) + ret = __i2c_write(adap, data, len); - if (i != len) + if (ret != len) return -1; - if (length && i2c_write_addr(adap, dev, I2C_READ_BIT, 1) != 0) - i = __i2c_read(adap, data, length); + if (dlen && i2c_write_addr(adap, chip_addr, + I2C_READ_BIT, 1) != 0) + ret = __i2c_read(adap, data, dlen); } else { - if ((!length || alen > 0) && - i2c_write_addr(adap, dev, I2C_WRITE_BIT, 0) != 0 && - __i2c_write(adap, &a[4 - alen], alen) == alen) - i = 0; /* No error so far */ + if ((!dlen || olen > 0) && + i2c_write_addr(adap, chip_addr, I2C_WRITE_BIT, 0) != 0 && + __i2c_write(adap, &o[4 - olen], olen) == olen) + ret = 0; /* No error so far */ - if (length && - i2c_write_addr(adap, dev, I2C_READ_BIT, alen ? 1 : 0) != 0) - i = __i2c_read(adap, data, length); + if (dlen && i2c_write_addr(adap, chip_addr, I2C_READ_BIT, + olen ? 1 : 0) != 0) + ret = __i2c_read(adap, data, dlen); } writeb(I2C_CR_MEN, &base->cr); @@ -468,35 +469,35 @@ fsl_i2c_read(struct i2c_adapter *adap, u8 dev, uint addr, int alen, u8 *data, if (i2c_wait4bus(adap)) /* Wait until STOP */ debug("i2c_read: wait4bus timed out\n"); - if (i == length) - return 0; + if (ret == dlen) + return 0; return -1; } static int -fsl_i2c_write(struct i2c_adapter *adap, u8 dev, uint addr, int alen, - u8 *data, int length) +fsl_i2c_write(struct i2c_adapter *adap, u8 chip_addr, uint offset, int olen, + u8 *data, int dlen) { struct fsl_i2c_base *base = (struct fsl_i2c_base *)i2c_base[adap->hwadapnr]; - int i = -1; /* signal error */ - u8 *a = (u8*)&addr; + int ret = -1; /* signal error */ + u8 *o = (u8 *)&offset; if (i2c_wait4bus(adap) < 0) return -1; - if (i2c_write_addr(adap, dev, I2C_WRITE_BIT, 0) != 0 && - __i2c_write(adap, &a[4 - alen], alen) == alen) { - i = __i2c_write(adap, data, length); + if (i2c_write_addr(adap, chip_addr, I2C_WRITE_BIT, 0) != 0 && + __i2c_write(adap, &o[4 - olen], olen) == olen) { + ret = __i2c_write(adap, data, dlen); } writeb(I2C_CR_MEN, &base->cr); if (i2c_wait4bus(adap)) /* Wait until STOP */ debug("i2c_write: wait4bus timed out\n"); - if (i == length) - return 0; + if (ret == dlen) + return 0; return -1; } From 386b276918541f4108b56f0c7c422b64396f64f2 Mon Sep 17 00:00:00 2001 From: "mario.six@gdsys.cc" Date: Mon, 25 Apr 2016 08:31:03 +0200 Subject: [PATCH 008/162] dm: fsl_i2c: Reword and clarify comment Signed-off-by: Mario Six --- drivers/i2c/fsl_i2c.c | 20 ++++++-------------- 1 file changed, 6 insertions(+), 14 deletions(-) diff --git a/drivers/i2c/fsl_i2c.c b/drivers/i2c/fsl_i2c.c index b0e65fcf65..18b8848ced 100644 --- a/drivers/i2c/fsl_i2c.c +++ b/drivers/i2c/fsl_i2c.c @@ -428,22 +428,14 @@ fsl_i2c_read(struct i2c_adapter *adap, u8 chip_addr, uint offset, int olen, if (i2c_wait4bus(adap) < 0) return -1; - /* To handle the need of I2C devices that require to write few bytes - * (more than 4 bytes of address as in the case of else part) - * of data before reading, Negative equivalent of dlen(bytes to write) - * is passed, but used the +ve part of len for writing data + /* Some drivers use offset lengths in excess of 4 bytes. These drivers + * adhere to the following convention: + * - the offset length is passed as negative (that is, the absolute + * value of olen is the actual offset length) + * - the offset itself is passed in data, which is overwritten by the + * subsequent read operation */ if (olen < 0) { - /* Generate a START and send the Address and - * the Tx Bytes to the slave. - * "START: Address: Write bytes data[len]" - * IF part supports writing any number of bytes in contrast - * to the else part, which supports writing address offset - * of upto 4 bytes only. - * bytes that need to be written are passed in - * "data", which will eventually keep the data READ, - * after writing the len bytes out of it - */ if (i2c_write_addr(adap, chip_addr, I2C_WRITE_BIT, 0) != 0) ret = __i2c_write(adap, data, len); From 03a112aad6893ab1059e716b7bfc36fe759eaec5 Mon Sep 17 00:00:00 2001 From: "mario.six@gdsys.cc" Date: Mon, 25 Apr 2016 08:31:04 +0200 Subject: [PATCH 009/162] dm: fsl_i2c: Remove unnecessary variable Signed-off-by: Mario Six --- drivers/i2c/fsl_i2c.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/i2c/fsl_i2c.c b/drivers/i2c/fsl_i2c.c index 18b8848ced..4bc1dda005 100644 --- a/drivers/i2c/fsl_i2c.c +++ b/drivers/i2c/fsl_i2c.c @@ -423,7 +423,6 @@ fsl_i2c_read(struct i2c_adapter *adap, u8 chip_addr, uint offset, int olen, (struct fsl_i2c_base *)i2c_base[adap->hwadapnr]; int ret = -1; /* signal error */ u8 *o = (u8 *)&offset; - int len = olen * -1; if (i2c_wait4bus(adap) < 0) return -1; @@ -437,9 +436,9 @@ fsl_i2c_read(struct i2c_adapter *adap, u8 chip_addr, uint offset, int olen, */ if (olen < 0) { if (i2c_write_addr(adap, chip_addr, I2C_WRITE_BIT, 0) != 0) - ret = __i2c_write(adap, data, len); + ret = __i2c_write(adap, data, -olen); - if (ret != len) + if (ret != -olen) return -1; if (dlen && i2c_write_addr(adap, chip_addr, From 16579ecbccb96a677ab468eba3e5a8e260751126 Mon Sep 17 00:00:00 2001 From: "mario.six@gdsys.cc" Date: Mon, 25 Apr 2016 08:31:05 +0200 Subject: [PATCH 010/162] dm: fsl_i2c: Rename probe method Signed-off-by: Mario Six --- drivers/i2c/fsl_i2c.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/i2c/fsl_i2c.c b/drivers/i2c/fsl_i2c.c index 4bc1dda005..3a3871338c 100644 --- a/drivers/i2c/fsl_i2c.c +++ b/drivers/i2c/fsl_i2c.c @@ -494,7 +494,7 @@ fsl_i2c_write(struct i2c_adapter *adap, u8 chip_addr, uint offset, int olen, } static int -fsl_i2c_probe(struct i2c_adapter *adap, uchar chip) +fsl_i2c_probe_chip(struct i2c_adapter *adap, uchar chip) { struct fsl_i2c_base *base = (struct fsl_i2c_base *)i2c_base[adap->hwadapnr]; @@ -524,24 +524,24 @@ static unsigned int fsl_i2c_set_bus_speed(struct i2c_adapter *adap, /* * Register fsl i2c adapters */ -U_BOOT_I2C_ADAP_COMPLETE(fsl_0, fsl_i2c_init, fsl_i2c_probe, fsl_i2c_read, +U_BOOT_I2C_ADAP_COMPLETE(fsl_0, fsl_i2c_init, fsl_i2c_probe_chip, fsl_i2c_read, fsl_i2c_write, fsl_i2c_set_bus_speed, CONFIG_SYS_FSL_I2C_SPEED, CONFIG_SYS_FSL_I2C_SLAVE, 0) #ifdef CONFIG_SYS_FSL_I2C2_OFFSET -U_BOOT_I2C_ADAP_COMPLETE(fsl_1, fsl_i2c_init, fsl_i2c_probe, fsl_i2c_read, +U_BOOT_I2C_ADAP_COMPLETE(fsl_1, fsl_i2c_init, fsl_i2c_probe_chip, fsl_i2c_read, fsl_i2c_write, fsl_i2c_set_bus_speed, CONFIG_SYS_FSL_I2C2_SPEED, CONFIG_SYS_FSL_I2C2_SLAVE, 1) #endif #ifdef CONFIG_SYS_FSL_I2C3_OFFSET -U_BOOT_I2C_ADAP_COMPLETE(fsl_2, fsl_i2c_init, fsl_i2c_probe, fsl_i2c_read, +U_BOOT_I2C_ADAP_COMPLETE(fsl_2, fsl_i2c_init, fsl_i2c_probe_chip, fsl_i2c_read, fsl_i2c_write, fsl_i2c_set_bus_speed, CONFIG_SYS_FSL_I2C3_SPEED, CONFIG_SYS_FSL_I2C3_SLAVE, 2) #endif #ifdef CONFIG_SYS_FSL_I2C4_OFFSET -U_BOOT_I2C_ADAP_COMPLETE(fsl_3, fsl_i2c_init, fsl_i2c_probe, fsl_i2c_read, +U_BOOT_I2C_ADAP_COMPLETE(fsl_3, fsl_i2c_init, fsl_i2c_probe_chip, fsl_i2c_read, fsl_i2c_write, fsl_i2c_set_bus_speed, CONFIG_SYS_FSL_I2C4_SPEED, CONFIG_SYS_FSL_I2C4_SLAVE, 3) From 00b61553f1248e7a57c3de6bf050a1489823db11 Mon Sep 17 00:00:00 2001 From: "mario.six@gdsys.cc" Date: Mon, 25 Apr 2016 08:31:06 +0200 Subject: [PATCH 011/162] dm: fsl_i2c: Rename methods for reading/writing data Signed-off-by: Mario Six --- drivers/i2c/fsl_i2c.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/i2c/fsl_i2c.c b/drivers/i2c/fsl_i2c.c index 3a3871338c..b838afdeea 100644 --- a/drivers/i2c/fsl_i2c.c +++ b/drivers/i2c/fsl_i2c.c @@ -366,7 +366,7 @@ i2c_write_addr(struct i2c_adapter *adap, u8 dev, u8 dir, int rsta) } static __inline__ int -__i2c_write(struct i2c_adapter *adap, u8 *data, int length) +__i2c_write_data(struct i2c_adapter *adap, u8 *data, int length) { struct fsl_i2c_base *base = (struct fsl_i2c_base *)i2c_base[adap->hwadapnr]; @@ -383,7 +383,7 @@ __i2c_write(struct i2c_adapter *adap, u8 *data, int length) } static __inline__ int -__i2c_read(struct i2c_adapter *adap, u8 *data, int length) +__i2c_read_data(struct i2c_adapter *adap, u8 *data, int length) { struct fsl_i2c_base *base = (struct fsl_i2c_base *)i2c_base[adap->hwadapnr]; @@ -436,23 +436,23 @@ fsl_i2c_read(struct i2c_adapter *adap, u8 chip_addr, uint offset, int olen, */ if (olen < 0) { if (i2c_write_addr(adap, chip_addr, I2C_WRITE_BIT, 0) != 0) - ret = __i2c_write(adap, data, -olen); + ret = __i2c_write_data(adap, data, -olen); if (ret != -olen) return -1; if (dlen && i2c_write_addr(adap, chip_addr, I2C_READ_BIT, 1) != 0) - ret = __i2c_read(adap, data, dlen); + ret = __i2c_read_data(adap, data, dlen); } else { if ((!dlen || olen > 0) && i2c_write_addr(adap, chip_addr, I2C_WRITE_BIT, 0) != 0 && - __i2c_write(adap, &o[4 - olen], olen) == olen) + __i2c_write_data(adap, &o[4 - olen], olen) == olen) ret = 0; /* No error so far */ if (dlen && i2c_write_addr(adap, chip_addr, I2C_READ_BIT, olen ? 1 : 0) != 0) - ret = __i2c_read(adap, data, dlen); + ret = __i2c_read_data(adap, data, dlen); } writeb(I2C_CR_MEN, &base->cr); @@ -479,8 +479,8 @@ fsl_i2c_write(struct i2c_adapter *adap, u8 chip_addr, uint offset, int olen, return -1; if (i2c_write_addr(adap, chip_addr, I2C_WRITE_BIT, 0) != 0 && - __i2c_write(adap, &o[4 - olen], olen) == olen) { - ret = __i2c_write(adap, data, dlen); + __i2c_write_data(adap, &o[4 - olen], olen) == olen) { + ret = __i2c_write_data(adap, data, dlen); } writeb(I2C_CR_MEN, &base->cr); From ad7e657cec8587b63dbf82d793cda54b74413a0a Mon Sep 17 00:00:00 2001 From: "mario.six@gdsys.cc" Date: Mon, 25 Apr 2016 08:31:07 +0200 Subject: [PATCH 012/162] dm: fsl_i2c: Prepare compatibility functions Signed-off-by: Mario Six --- drivers/i2c/fsl_i2c.c | 47 +++++++++++++++++++++++++++++++++++-------- 1 file changed, 39 insertions(+), 8 deletions(-) diff --git a/drivers/i2c/fsl_i2c.c b/drivers/i2c/fsl_i2c.c index b838afdeea..06f1db43fb 100644 --- a/drivers/i2c/fsl_i2c.c +++ b/drivers/i2c/fsl_i2c.c @@ -247,7 +247,7 @@ err: return ret; } -static void fsl_i2c_init(struct i2c_adapter *adap, int speed, int slaveadd) +static void __i2c_init(struct i2c_adapter *adap, int speed, int slaveadd) { const struct fsl_i2c_base *base; const unsigned long long timeout = usec2ticks(CONFIG_I2C_MBB_TIMEOUT); @@ -416,8 +416,8 @@ __i2c_read_data(struct i2c_adapter *adap, u8 *data, int length) } static int -fsl_i2c_read(struct i2c_adapter *adap, u8 chip_addr, uint offset, int olen, - u8 *data, int dlen) +__i2c_read(struct i2c_adapter *adap, u8 chip_addr, uint offset, int olen, + u8 *data, int dlen) { struct fsl_i2c_base *base = (struct fsl_i2c_base *)i2c_base[adap->hwadapnr]; @@ -467,8 +467,8 @@ fsl_i2c_read(struct i2c_adapter *adap, u8 chip_addr, uint offset, int olen, } static int -fsl_i2c_write(struct i2c_adapter *adap, u8 chip_addr, uint offset, int olen, - u8 *data, int dlen) +__i2c_write(struct i2c_adapter *adap, u8 chip_addr, uint offset, int olen, + u8 *data, int dlen) { struct fsl_i2c_base *base = (struct fsl_i2c_base *)i2c_base[adap->hwadapnr]; @@ -494,7 +494,7 @@ fsl_i2c_write(struct i2c_adapter *adap, u8 chip_addr, uint offset, int olen, } static int -fsl_i2c_probe_chip(struct i2c_adapter *adap, uchar chip) +__i2c_probe_chip(struct i2c_adapter *adap, uchar chip) { struct fsl_i2c_base *base = (struct fsl_i2c_base *)i2c_base[adap->hwadapnr]; @@ -505,10 +505,10 @@ fsl_i2c_probe_chip(struct i2c_adapter *adap, uchar chip) if (chip == (readb(&base->adr) >> 1)) return -1; - return fsl_i2c_read(adap, chip, 0, 0, NULL, 0); + return __i2c_read(adap, chip, 0, 0, NULL, 0); } -static unsigned int fsl_i2c_set_bus_speed(struct i2c_adapter *adap, +static unsigned int __i2c_set_bus_speed(struct i2c_adapter *adap, unsigned int speed) { struct fsl_i2c_base *base = @@ -521,6 +521,37 @@ static unsigned int fsl_i2c_set_bus_speed(struct i2c_adapter *adap, return 0; } +static void fsl_i2c_init(struct i2c_adapter *adap, int speed, int slaveadd) +{ + __i2c_init(adap, speed, slaveadd); +} + +static int +fsl_i2c_probe_chip(struct i2c_adapter *adap, uchar chip) +{ + return __i2c_probe_chip(adap, chip); +} + +static int +fsl_i2c_read(struct i2c_adapter *adap, u8 chip_addr, uint offset, int olen, + u8 *data, int dlen) +{ + return __i2c_read(adap, chip_addr, offset, olen, data, dlen); +} + +static int +fsl_i2c_write(struct i2c_adapter *adap, u8 chip_addr, uint offset, int olen, + u8 *data, int dlen) +{ + return __i2c_write(adap, chip_addr, offset, olen, data, dlen); +} + +static unsigned int fsl_i2c_set_bus_speed(struct i2c_adapter *adap, + unsigned int speed) +{ + return __i2c_set_bus_speed(adap, speed); +} + /* * Register fsl i2c adapters */ From ecf591e303ed576817f0638ade56e2fab7d910c8 Mon Sep 17 00:00:00 2001 From: "mario.six@gdsys.cc" Date: Mon, 25 Apr 2016 08:31:08 +0200 Subject: [PATCH 013/162] dm: fsl_i2c: Factor out adap parameter Signed-off-by: Mario Six --- drivers/i2c/fsl_i2c.c | 116 ++++++++++++++++++------------------------ 1 file changed, 49 insertions(+), 67 deletions(-) diff --git a/drivers/i2c/fsl_i2c.c b/drivers/i2c/fsl_i2c.c index 06f1db43fb..7d99f48467 100644 --- a/drivers/i2c/fsl_i2c.c +++ b/drivers/i2c/fsl_i2c.c @@ -247,9 +247,9 @@ err: return ret; } -static void __i2c_init(struct i2c_adapter *adap, int speed, int slaveadd) +static void __i2c_init(const struct fsl_i2c_base *base, int speed, int + slaveadd, int i2c_clk, int busnum) { - const struct fsl_i2c_base *base; const unsigned long long timeout = usec2ticks(CONFIG_I2C_MBB_TIMEOUT); unsigned long long timeval; @@ -260,11 +260,9 @@ static void __i2c_init(struct i2c_adapter *adap, int speed, int slaveadd) */ i2c_init_board(); #endif - base = (struct fsl_i2c_base *)i2c_base[adap->hwadapnr]; - writeb(0, &base->cr); /* stop I2C controller */ udelay(5); /* let it shutdown in peace */ - set_i2c_bus_speed(base, get_i2c_clock(adap->hwadapnr), speed); + set_i2c_bus_speed(base, i2c_clk, speed); writeb(slaveadd << 1, &base->adr);/* write slave address */ writeb(0x0, &base->sr); /* clear status register */ writeb(I2C_CR_MEN, &base->cr); /* start I2C controller */ @@ -276,7 +274,7 @@ static void __i2c_init(struct i2c_adapter *adap, int speed, int slaveadd) if (fsl_i2c_fixup(base)) debug("i2c_init: BUS#%d failed to init\n", - adap->hwadapnr); + busnum); break; } @@ -292,10 +290,8 @@ static void __i2c_init(struct i2c_adapter *adap, int speed, int slaveadd) } static int -i2c_wait4bus(struct i2c_adapter *adap) +i2c_wait4bus(const struct fsl_i2c_base *base) { - struct fsl_i2c_base *base = - (struct fsl_i2c_base *)i2c_base[adap->hwadapnr]; unsigned long long timeval = get_ticks(); const unsigned long long timeout = usec2ticks(CONFIG_I2C_MBB_TIMEOUT); @@ -307,14 +303,12 @@ i2c_wait4bus(struct i2c_adapter *adap) return 0; } -static __inline__ int -i2c_wait(struct i2c_adapter *adap, int write) +static inline int +i2c_wait(const struct fsl_i2c_base *base, int write) { u32 csr; unsigned long long timeval = get_ticks(); const unsigned long long timeout = usec2ticks(CONFIG_I2C_TIMEOUT); - struct fsl_i2c_base *base = - (struct fsl_i2c_base *)i2c_base[adap->hwadapnr]; do { csr = readb(&base->sr); @@ -347,46 +341,39 @@ i2c_wait(struct i2c_adapter *adap, int write) return -1; } -static __inline__ int -i2c_write_addr(struct i2c_adapter *adap, u8 dev, u8 dir, int rsta) +static inline int +i2c_write_addr(const struct fsl_i2c_base *base, u8 dev, u8 dir, int rsta) { - struct fsl_i2c_base *base = - (struct fsl_i2c_base *)i2c_base[adap->hwadapnr]; - writeb(I2C_CR_MEN | I2C_CR_MSTA | I2C_CR_MTX | (rsta ? I2C_CR_RSTA : 0), &base->cr); writeb((dev << 1) | dir, &base->dr); - if (i2c_wait(adap, I2C_WRITE_BIT) < 0) + if (i2c_wait(base, I2C_WRITE_BIT) < 0) return 0; return 1; } -static __inline__ int -__i2c_write_data(struct i2c_adapter *adap, u8 *data, int length) +static inline int +__i2c_write_data(const struct fsl_i2c_base *base, u8 *data, int length) { - struct fsl_i2c_base *base = - (struct fsl_i2c_base *)i2c_base[adap->hwadapnr]; int i; for (i = 0; i < length; i++) { writeb(data[i], &base->dr); - if (i2c_wait(adap, I2C_WRITE_BIT) < 0) + if (i2c_wait(base, I2C_WRITE_BIT) < 0) break; } return i; } -static __inline__ int -__i2c_read_data(struct i2c_adapter *adap, u8 *data, int length) +static inline int +__i2c_read_data(const struct fsl_i2c_base *base, u8 *data, int length) { - struct fsl_i2c_base *base = - (struct fsl_i2c_base *)i2c_base[adap->hwadapnr]; int i; writeb(I2C_CR_MEN | I2C_CR_MSTA | ((length == 1) ? I2C_CR_TXAK : 0), @@ -396,7 +383,7 @@ __i2c_read_data(struct i2c_adapter *adap, u8 *data, int length) readb(&base->dr); for (i = 0; i < length; i++) { - if (i2c_wait(adap, I2C_READ_BIT) < 0) + if (i2c_wait(base, I2C_READ_BIT) < 0) break; /* Generate ack on last next to last byte */ @@ -416,15 +403,12 @@ __i2c_read_data(struct i2c_adapter *adap, u8 *data, int length) } static int -__i2c_read(struct i2c_adapter *adap, u8 chip_addr, uint offset, int olen, +__i2c_read(const struct fsl_i2c_base *base, u8 chip_addr, u8 *offset, int olen, u8 *data, int dlen) { - struct fsl_i2c_base *base = - (struct fsl_i2c_base *)i2c_base[adap->hwadapnr]; int ret = -1; /* signal error */ - u8 *o = (u8 *)&offset; - if (i2c_wait4bus(adap) < 0) + if (i2c_wait4bus(base) < 0) return -1; /* Some drivers use offset lengths in excess of 4 bytes. These drivers @@ -435,29 +419,29 @@ __i2c_read(struct i2c_adapter *adap, u8 chip_addr, uint offset, int olen, * subsequent read operation */ if (olen < 0) { - if (i2c_write_addr(adap, chip_addr, I2C_WRITE_BIT, 0) != 0) - ret = __i2c_write_data(adap, data, -olen); + if (i2c_write_addr(base, chip_addr, I2C_WRITE_BIT, 0) != 0) + ret = __i2c_write_data(base, data, -olen); if (ret != -olen) return -1; - if (dlen && i2c_write_addr(adap, chip_addr, + if (dlen && i2c_write_addr(base, chip_addr, I2C_READ_BIT, 1) != 0) - ret = __i2c_read_data(adap, data, dlen); + ret = __i2c_read_data(base, data, dlen); } else { if ((!dlen || olen > 0) && - i2c_write_addr(adap, chip_addr, I2C_WRITE_BIT, 0) != 0 && - __i2c_write_data(adap, &o[4 - olen], olen) == olen) + i2c_write_addr(base, chip_addr, I2C_WRITE_BIT, 0) != 0 && + __i2c_write_data(base, offset, olen) == olen) ret = 0; /* No error so far */ - if (dlen && i2c_write_addr(adap, chip_addr, I2C_READ_BIT, + if (dlen && i2c_write_addr(base, chip_addr, I2C_READ_BIT, olen ? 1 : 0) != 0) - ret = __i2c_read_data(adap, data, dlen); + ret = __i2c_read_data(base, data, dlen); } writeb(I2C_CR_MEN, &base->cr); - if (i2c_wait4bus(adap)) /* Wait until STOP */ + if (i2c_wait4bus(base)) /* Wait until STOP */ debug("i2c_read: wait4bus timed out\n"); if (ret == dlen) @@ -467,24 +451,21 @@ __i2c_read(struct i2c_adapter *adap, u8 chip_addr, uint offset, int olen, } static int -__i2c_write(struct i2c_adapter *adap, u8 chip_addr, uint offset, int olen, +__i2c_write(const struct fsl_i2c_base *base, u8 chip_addr, u8 *offset, int olen, u8 *data, int dlen) { - struct fsl_i2c_base *base = - (struct fsl_i2c_base *)i2c_base[adap->hwadapnr]; int ret = -1; /* signal error */ - u8 *o = (u8 *)&offset; - if (i2c_wait4bus(adap) < 0) + if (i2c_wait4bus(base) < 0) return -1; - if (i2c_write_addr(adap, chip_addr, I2C_WRITE_BIT, 0) != 0 && - __i2c_write_data(adap, &o[4 - olen], olen) == olen) { - ret = __i2c_write_data(adap, data, dlen); + if (i2c_write_addr(base, chip_addr, I2C_WRITE_BIT, 0) != 0 && + __i2c_write_data(base, offset, olen) == olen) { + ret = __i2c_write_data(base, data, dlen); } writeb(I2C_CR_MEN, &base->cr); - if (i2c_wait4bus(adap)) /* Wait until STOP */ + if (i2c_wait4bus(base)) /* Wait until STOP */ debug("i2c_write: wait4bus timed out\n"); if (ret == dlen) @@ -494,10 +475,8 @@ __i2c_write(struct i2c_adapter *adap, u8 chip_addr, uint offset, int olen, } static int -__i2c_probe_chip(struct i2c_adapter *adap, uchar chip) +__i2c_probe_chip(const struct fsl_i2c_base *base, uchar chip) { - struct fsl_i2c_base *base = - (struct fsl_i2c_base *)i2c_base[adap->hwadapnr]; /* For unknow reason the controller will ACK when * probing for a slave with the same address, so skip * it. @@ -505,17 +484,14 @@ __i2c_probe_chip(struct i2c_adapter *adap, uchar chip) if (chip == (readb(&base->adr) >> 1)) return -1; - return __i2c_read(adap, chip, 0, 0, NULL, 0); + return __i2c_read(base, chip, 0, 0, NULL, 0); } -static unsigned int __i2c_set_bus_speed(struct i2c_adapter *adap, - unsigned int speed) +static unsigned int __i2c_set_bus_speed(const struct fsl_i2c_base *base, + unsigned int speed, int i2c_clk) { - struct fsl_i2c_base *base = - (struct fsl_i2c_base *)i2c_base[adap->hwadapnr]; - writeb(0, &base->cr); /* stop controller */ - set_i2c_bus_speed(base, get_i2c_clock(adap->hwadapnr), speed); + set_i2c_bus_speed(base, i2c_clk, speed); writeb(I2C_CR_MEN, &base->cr); /* start controller */ return 0; @@ -523,33 +499,39 @@ static unsigned int __i2c_set_bus_speed(struct i2c_adapter *adap, static void fsl_i2c_init(struct i2c_adapter *adap, int speed, int slaveadd) { - __i2c_init(adap, speed, slaveadd); + __i2c_init(i2c_base[adap->hwadapnr], speed, slaveadd, + get_i2c_clock(adap->hwadapnr), adap->hwadapnr); } static int fsl_i2c_probe_chip(struct i2c_adapter *adap, uchar chip) { - return __i2c_probe_chip(adap, chip); + return __i2c_probe_chip(i2c_base[adap->hwadapnr], chip); } static int fsl_i2c_read(struct i2c_adapter *adap, u8 chip_addr, uint offset, int olen, u8 *data, int dlen) { - return __i2c_read(adap, chip_addr, offset, olen, data, dlen); + u8 *o = (u8 *)&offset; + return __i2c_read(i2c_base[adap->hwadapnr], chip_addr, &o[4 - olen], + olen, data, dlen); } static int fsl_i2c_write(struct i2c_adapter *adap, u8 chip_addr, uint offset, int olen, u8 *data, int dlen) { - return __i2c_write(adap, chip_addr, offset, olen, data, dlen); + u8 *o = (u8 *)&offset; + return __i2c_write(i2c_base[adap->hwadapnr], chip_addr, &o[4 - olen], + olen, data, dlen); } static unsigned int fsl_i2c_set_bus_speed(struct i2c_adapter *adap, unsigned int speed) { - return __i2c_set_bus_speed(adap, speed); + return __i2c_set_bus_speed(i2c_base[adap->hwadapnr], speed, + get_i2c_clock(adap->hwadapnr)); } /* From dbc82ce31b4e90ed171c10e02d382d36bf201dc4 Mon Sep 17 00:00:00 2001 From: "mario.six@gdsys.cc" Date: Mon, 25 Apr 2016 08:31:09 +0200 Subject: [PATCH 014/162] dm: fsl_i2c: Enable DM for FSL I2C Signed-off-by: Mario Six --- arch/powerpc/include/asm/fsl_i2c.h | 10 +++ drivers/i2c/Kconfig | 7 ++ drivers/i2c/fsl_i2c.c | 103 +++++++++++++++++++++++++++++ 3 files changed, 120 insertions(+) diff --git a/arch/powerpc/include/asm/fsl_i2c.h b/arch/powerpc/include/asm/fsl_i2c.h index e94bdc690e..d2586f94f5 100644 --- a/arch/powerpc/include/asm/fsl_i2c.h +++ b/arch/powerpc/include/asm/fsl_i2c.h @@ -68,4 +68,14 @@ typedef struct fsl_i2c_base { u8 res6[0xE8]; } fsl_i2c_t; +#ifdef CONFIG_DM_I2C +struct fsl_i2c_dev { + struct fsl_i2c_base __iomem *base; /* register base */ + u32 i2c_clk; + u32 index; + u8 slaveadd; + uint speed; +}; +#endif + #endif /* _ASM_I2C_H_ */ diff --git a/drivers/i2c/Kconfig b/drivers/i2c/Kconfig index 9324c6c9e5..ffe18f702c 100644 --- a/drivers/i2c/Kconfig +++ b/drivers/i2c/Kconfig @@ -58,6 +58,13 @@ config DM_I2C_GPIO bindings are supported. Binding info: doc/device-tree-bindings/i2c/i2c-gpio.txt +config SYS_I2C_FSL + bool "Freescale I2C bus driver" + depends on DM_I2C + help + Add support for Freescale I2C busses as used on MPC8240, MPC8245, and + MPC85xx processors. + config SYS_I2C_CADENCE tristate "Cadence I2C Controller" depends on DM_I2C && (ARCH_ZYNQ || ARM64) diff --git a/drivers/i2c/fsl_i2c.c b/drivers/i2c/fsl_i2c.c index 7d99f48467..b8cc647bd3 100644 --- a/drivers/i2c/fsl_i2c.c +++ b/drivers/i2c/fsl_i2c.c @@ -12,6 +12,8 @@ #include /* Functional interface */ #include #include /* HW definitions */ +#include +#include /* The maximum number of microseconds we will wait until another master has * released the bus. If not defined in the board header file, then use a @@ -34,6 +36,7 @@ DECLARE_GLOBAL_DATA_PTR; +#ifndef CONFIG_DM_I2C static const struct fsl_i2c_base *i2c_base[4] = { (struct fsl_i2c_base *)(CONFIG_SYS_IMMR + CONFIG_SYS_FSL_I2C_OFFSET), #ifdef CONFIG_SYS_FSL_I2C2_OFFSET @@ -46,6 +49,7 @@ static const struct fsl_i2c_base *i2c_base[4] = { (struct fsl_i2c_base *)(CONFIG_SYS_IMMR + CONFIG_SYS_FSL_I2C4_OFFSET) #endif }; +#endif /* I2C speed map for a DFSR value of 1 */ @@ -192,6 +196,7 @@ static unsigned int set_i2c_bus_speed(const struct fsl_i2c_base *base, return speed; } +#ifndef CONFIG_DM_I2C static unsigned int get_i2c_clock(int bus) { if (bus) @@ -199,6 +204,7 @@ static unsigned int get_i2c_clock(int bus) else return gd->arch.i2c1_clk; /* I2C1 clock */ } +#endif static int fsl_i2c_fixup(const struct fsl_i2c_base *base) { @@ -497,6 +503,7 @@ static unsigned int __i2c_set_bus_speed(const struct fsl_i2c_base *base, return 0; } +#ifndef CONFIG_DM_I2C static void fsl_i2c_init(struct i2c_adapter *adap, int speed, int slaveadd) { __i2c_init(i2c_base[adap->hwadapnr], speed, slaveadd, @@ -559,3 +566,99 @@ U_BOOT_I2C_ADAP_COMPLETE(fsl_3, fsl_i2c_init, fsl_i2c_probe_chip, fsl_i2c_read, CONFIG_SYS_FSL_I2C4_SPEED, CONFIG_SYS_FSL_I2C4_SLAVE, 3) #endif +#else /* CONFIG_DM_I2C */ +static int fsl_i2c_probe_chip(struct udevice *bus, u32 chip_addr, + u32 chip_flags) +{ + struct fsl_i2c_dev *dev = dev_get_priv(bus); + return __i2c_probe_chip(dev->base, chip_addr); +} + +static int fsl_i2c_set_bus_speed(struct udevice *bus, unsigned int speed) +{ + struct fsl_i2c_dev *dev = dev_get_priv(bus); + return __i2c_set_bus_speed(dev->base, speed, dev->i2c_clk); +} + +static int fsl_i2c_ofdata_to_platdata(struct udevice *bus) +{ + struct fsl_i2c_dev *dev = dev_get_priv(bus); + u64 reg; + u32 addr, size; + + reg = fdtdec_get_addr(gd->fdt_blob, bus->of_offset, "reg"); + addr = reg >> 32; + size = reg & 0xFFFFFFFF; + + dev->base = map_sysmem(CONFIG_SYS_IMMR + addr, size); + + if (!dev->base) + return -ENOMEM; + + dev->index = fdtdec_get_int(gd->fdt_blob, bus->of_offset, + "cell-index", -1); + dev->slaveadd = fdtdec_get_int(gd->fdt_blob, bus->of_offset, + "u-boot,i2c-slave-addr", 0x7f); + dev->speed = fdtdec_get_int(gd->fdt_blob, bus->of_offset, + "clock-frequency", 400000); + + dev->i2c_clk = dev->index ? gd->arch.i2c2_clk : gd->arch.i2c1_clk; + + return 0; +} + +static int fsl_i2c_probe(struct udevice *bus) +{ + struct fsl_i2c_dev *dev = dev_get_priv(bus); + __i2c_init(dev->base, dev->speed, dev->slaveadd, dev->i2c_clk, + dev->index); + return 0; +} + +static int fsl_i2c_xfer(struct udevice *bus, struct i2c_msg *msg, int nmsgs) +{ + struct fsl_i2c_dev *dev = dev_get_priv(bus); + struct i2c_msg *dmsg, *omsg, dummy; + + memset(&dummy, 0, sizeof(struct i2c_msg)); + + /* We expect either two messages (one with an offset and one with the + * actucal data) or one message (just data) */ + if (nmsgs > 2 || nmsgs == 0) { + debug("%s: Only one or two messages are supported.", __func__); + return -1; + } + + omsg = nmsgs == 1 ? &dummy : msg; + dmsg = nmsgs == 1 ? msg : msg + 1; + + if (dmsg->flags & I2C_M_RD) + return __i2c_read(dev->base, dmsg->addr, omsg->buf, omsg->len, + dmsg->buf, dmsg->len); + else + return __i2c_write(dev->base, dmsg->addr, omsg->buf, omsg->len, + dmsg->buf, dmsg->len); +} + +static const struct dm_i2c_ops fsl_i2c_ops = { + .xfer = fsl_i2c_xfer, + .probe_chip = fsl_i2c_probe_chip, + .set_bus_speed = fsl_i2c_set_bus_speed, +}; + +static const struct udevice_id fsl_i2c_ids[] = { + { .compatible = "fsl-i2c", }, + { /* sentinel */ } +}; + +U_BOOT_DRIVER(i2c_fsl) = { + .name = "i2c_fsl", + .id = UCLASS_I2C, + .of_match = fsl_i2c_ids, + .probe = fsl_i2c_probe, + .ofdata_to_platdata = fsl_i2c_ofdata_to_platdata, + .priv_auto_alloc_size = sizeof(struct fsl_i2c_dev), + .ops = &fsl_i2c_ops, +}; + +#endif /* CONFIG_DM_I2C */ From e32d0db7985eece55ad099c6c86d00d441fdf48c Mon Sep 17 00:00:00 2001 From: Stefan Roese Date: Thu, 28 Apr 2016 09:47:17 +0200 Subject: [PATCH 015/162] i2c: Add entry for Designware I2C driver in Kconfig This patch adds an entry for the Designware I2C driver in Kconfig. Signed-off-by: Stefan Roese Cc: Heiko Schocher Reviewed-by: Bin Meng --- drivers/i2c/Kconfig | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/i2c/Kconfig b/drivers/i2c/Kconfig index ffe18f702c..193b9f59b8 100644 --- a/drivers/i2c/Kconfig +++ b/drivers/i2c/Kconfig @@ -72,6 +72,14 @@ config SYS_I2C_CADENCE Say yes here to select Cadence I2C Host Controller. This controller is e.g. used by Xilinx Zynq. +config SYS_I2C_DW + bool "Designware I2C Controller" + default n + help + Say yes here to select the Designware I2C Host Controller. This + controller is used in various SoCs, e.g. the ST SPEAr, Altera + SoCFPGA, Synopsys ARC700 and some Intel x86 SoCs. + config SYS_I2C_INTEL bool "Intel I2C/SMBUS driver" depends on DM_I2C From 4d5e9b39e21152734ffa4b533efbb83f278df18b Mon Sep 17 00:00:00 2001 From: Stefan Roese Date: Thu, 28 Apr 2016 09:47:18 +0200 Subject: [PATCH 016/162] i2c: config: Move SYS_I2C_DW to Kconfig This patch moves all appearances of CONFIG_SYS_I2C_DW from the config header to the defconfig files. Signed-off-by: Stefan Roese Cc: Heiko Schocher Cc: Alexey Brodkin --- configs/axs101_defconfig | 1 + configs/axs103_defconfig | 1 + configs/socfpga_arria5_defconfig | 1 + configs/socfpga_cyclone5_defconfig | 1 + configs/socfpga_de0_nano_soc_defconfig | 1 + configs/socfpga_mcvevk_defconfig | 1 + configs/socfpga_sockit_defconfig | 1 + configs/socfpga_socrates_defconfig | 1 + configs/socfpga_sr1500_defconfig | 1 + configs/spear300_defconfig | 1 + configs/spear300_nand_defconfig | 1 + configs/spear300_usbtty_defconfig | 1 + configs/spear300_usbtty_nand_defconfig | 1 + configs/spear310_defconfig | 1 + configs/spear310_nand_defconfig | 1 + configs/spear310_pnor_defconfig | 1 + configs/spear310_usbtty_defconfig | 1 + configs/spear310_usbtty_nand_defconfig | 1 + configs/spear310_usbtty_pnor_defconfig | 1 + configs/spear320_defconfig | 1 + configs/spear320_nand_defconfig | 1 + configs/spear320_pnor_defconfig | 1 + configs/spear320_usbtty_defconfig | 1 + configs/spear320_usbtty_nand_defconfig | 1 + configs/spear320_usbtty_pnor_defconfig | 1 + configs/spear600_defconfig | 1 + configs/spear600_nand_defconfig | 1 + configs/spear600_usbtty_defconfig | 1 + configs/spear600_usbtty_nand_defconfig | 1 + configs/x600_defconfig | 1 + include/configs/axs101.h | 1 - include/configs/socfpga_common.h | 1 - include/configs/spear-common.h | 1 - include/configs/x600.h | 1 - 34 files changed, 30 insertions(+), 4 deletions(-) diff --git a/configs/axs101_defconfig b/configs/axs101_defconfig index 85af09eeb6..07a6a1855e 100644 --- a/configs/axs101_defconfig +++ b/configs/axs101_defconfig @@ -18,6 +18,7 @@ CONFIG_OF_EMBED=y CONFIG_NET_RANDOM_ETHADDR=y CONFIG_DM=y CONFIG_CLK=y +CONFIG_SYS_I2C_DW=y CONFIG_DM_ETH=y CONFIG_ETH_DESIGNWARE=y CONFIG_SYS_NS16550=y diff --git a/configs/axs103_defconfig b/configs/axs103_defconfig index aa9bf336b1..01a51432ac 100644 --- a/configs/axs103_defconfig +++ b/configs/axs103_defconfig @@ -18,6 +18,7 @@ CONFIG_OF_EMBED=y CONFIG_NET_RANDOM_ETHADDR=y CONFIG_DM=y CONFIG_CLK=y +CONFIG_SYS_I2C_DW=y CONFIG_DM_ETH=y CONFIG_ETH_DESIGNWARE=y CONFIG_SYS_NS16550=y diff --git a/configs/socfpga_arria5_defconfig b/configs/socfpga_arria5_defconfig index 9a7c091569..a662e72cc7 100644 --- a/configs/socfpga_arria5_defconfig +++ b/configs/socfpga_arria5_defconfig @@ -33,6 +33,7 @@ CONFIG_CMD_FAT=y CONFIG_CMD_FS_GENERIC=y CONFIG_SPL_DM_SEQ_ALIAS=y CONFIG_DWAPB_GPIO=y +CONFIG_SYS_I2C_DW=y CONFIG_DM_MMC=y CONFIG_SPI_FLASH=y CONFIG_SPI_FLASH_BAR=y diff --git a/configs/socfpga_cyclone5_defconfig b/configs/socfpga_cyclone5_defconfig index ac81854f40..b2933f778a 100644 --- a/configs/socfpga_cyclone5_defconfig +++ b/configs/socfpga_cyclone5_defconfig @@ -33,6 +33,7 @@ CONFIG_CMD_FAT=y CONFIG_CMD_FS_GENERIC=y CONFIG_SPL_DM_SEQ_ALIAS=y CONFIG_DWAPB_GPIO=y +CONFIG_SYS_I2C_DW=y CONFIG_DM_MMC=y CONFIG_SPI_FLASH=y CONFIG_SPI_FLASH_BAR=y diff --git a/configs/socfpga_de0_nano_soc_defconfig b/configs/socfpga_de0_nano_soc_defconfig index 405d9d4079..f197b6d2b0 100644 --- a/configs/socfpga_de0_nano_soc_defconfig +++ b/configs/socfpga_de0_nano_soc_defconfig @@ -32,6 +32,7 @@ CONFIG_CMD_EXT4_WRITE=y CONFIG_CMD_FAT=y CONFIG_CMD_FS_GENERIC=y CONFIG_DWAPB_GPIO=y +CONFIG_SYS_I2C_DW=y CONFIG_DM_MMC=y CONFIG_DM_ETH=y CONFIG_ETH_DESIGNWARE=y diff --git a/configs/socfpga_mcvevk_defconfig b/configs/socfpga_mcvevk_defconfig index 36154901aa..6624f9e07d 100644 --- a/configs/socfpga_mcvevk_defconfig +++ b/configs/socfpga_mcvevk_defconfig @@ -32,6 +32,7 @@ CONFIG_CMD_EXT4_WRITE=y CONFIG_CMD_FAT=y CONFIG_CMD_FS_GENERIC=y CONFIG_DWAPB_GPIO=y +CONFIG_SYS_I2C_DW=y CONFIG_DM_MMC=y CONFIG_DM_ETH=y CONFIG_ETH_DESIGNWARE=y diff --git a/configs/socfpga_sockit_defconfig b/configs/socfpga_sockit_defconfig index bdc8e6b26d..c6414f8be5 100644 --- a/configs/socfpga_sockit_defconfig +++ b/configs/socfpga_sockit_defconfig @@ -33,6 +33,7 @@ CONFIG_CMD_FAT=y CONFIG_CMD_FS_GENERIC=y CONFIG_SPL_DM_SEQ_ALIAS=y CONFIG_DWAPB_GPIO=y +CONFIG_SYS_I2C_DW=y CONFIG_DM_MMC=y CONFIG_SPI_FLASH=y CONFIG_SPI_FLASH_BAR=y diff --git a/configs/socfpga_socrates_defconfig b/configs/socfpga_socrates_defconfig index a17e9d0fd9..b47a5602b8 100644 --- a/configs/socfpga_socrates_defconfig +++ b/configs/socfpga_socrates_defconfig @@ -34,6 +34,7 @@ CONFIG_CMD_FAT=y CONFIG_CMD_FS_GENERIC=y CONFIG_SPL_DM_SEQ_ALIAS=y CONFIG_DWAPB_GPIO=y +CONFIG_SYS_I2C_DW=y CONFIG_DM_MMC=y CONFIG_SPI_FLASH=y CONFIG_SPI_FLASH_BAR=y diff --git a/configs/socfpga_sr1500_defconfig b/configs/socfpga_sr1500_defconfig index c4b215ad1f..aab4498973 100644 --- a/configs/socfpga_sr1500_defconfig +++ b/configs/socfpga_sr1500_defconfig @@ -32,6 +32,7 @@ CONFIG_CMD_FAT=y CONFIG_CMD_FS_GENERIC=y CONFIG_SPL_DM_SEQ_ALIAS=y CONFIG_DWAPB_GPIO=y +CONFIG_SYS_I2C_DW=y CONFIG_DM_MMC=y CONFIG_SPI_FLASH=y CONFIG_SPI_FLASH_BAR=y diff --git a/configs/spear300_defconfig b/configs/spear300_defconfig index af2f54486a..db3b6ea6c5 100644 --- a/configs/spear300_defconfig +++ b/configs/spear300_defconfig @@ -6,5 +6,6 @@ CONFIG_CMD_I2C=y CONFIG_CMD_DHCP=y CONFIG_CMD_MII=y CONFIG_CMD_PING=y +CONFIG_SYS_I2C_DW=y CONFIG_NETDEVICES=y CONFIG_ETH_DESIGNWARE=y diff --git a/configs/spear300_nand_defconfig b/configs/spear300_nand_defconfig index 6c53e1f0b5..ea4e8d772a 100644 --- a/configs/spear300_nand_defconfig +++ b/configs/spear300_nand_defconfig @@ -6,5 +6,6 @@ CONFIG_CMD_I2C=y CONFIG_CMD_DHCP=y CONFIG_CMD_MII=y CONFIG_CMD_PING=y +CONFIG_SYS_I2C_DW=y CONFIG_NETDEVICES=y CONFIG_ETH_DESIGNWARE=y diff --git a/configs/spear300_usbtty_defconfig b/configs/spear300_usbtty_defconfig index 6827701ce3..a2b56f384a 100644 --- a/configs/spear300_usbtty_defconfig +++ b/configs/spear300_usbtty_defconfig @@ -6,5 +6,6 @@ CONFIG_CMD_I2C=y CONFIG_CMD_DHCP=y CONFIG_CMD_MII=y CONFIG_CMD_PING=y +CONFIG_SYS_I2C_DW=y CONFIG_NETDEVICES=y CONFIG_ETH_DESIGNWARE=y diff --git a/configs/spear300_usbtty_nand_defconfig b/configs/spear300_usbtty_nand_defconfig index 477a226033..173848959d 100644 --- a/configs/spear300_usbtty_nand_defconfig +++ b/configs/spear300_usbtty_nand_defconfig @@ -6,5 +6,6 @@ CONFIG_CMD_I2C=y CONFIG_CMD_DHCP=y CONFIG_CMD_MII=y CONFIG_CMD_PING=y +CONFIG_SYS_I2C_DW=y CONFIG_NETDEVICES=y CONFIG_ETH_DESIGNWARE=y diff --git a/configs/spear310_defconfig b/configs/spear310_defconfig index 0991f8ecb6..a6064a5d90 100644 --- a/configs/spear310_defconfig +++ b/configs/spear310_defconfig @@ -6,5 +6,6 @@ CONFIG_CMD_I2C=y CONFIG_CMD_DHCP=y CONFIG_CMD_MII=y CONFIG_CMD_PING=y +CONFIG_SYS_I2C_DW=y CONFIG_NETDEVICES=y CONFIG_ETH_DESIGNWARE=y diff --git a/configs/spear310_nand_defconfig b/configs/spear310_nand_defconfig index ef30a6785b..85944c68f1 100644 --- a/configs/spear310_nand_defconfig +++ b/configs/spear310_nand_defconfig @@ -6,5 +6,6 @@ CONFIG_CMD_I2C=y CONFIG_CMD_DHCP=y CONFIG_CMD_MII=y CONFIG_CMD_PING=y +CONFIG_SYS_I2C_DW=y CONFIG_NETDEVICES=y CONFIG_ETH_DESIGNWARE=y diff --git a/configs/spear310_pnor_defconfig b/configs/spear310_pnor_defconfig index 6cfe22088c..48efe3d948 100644 --- a/configs/spear310_pnor_defconfig +++ b/configs/spear310_pnor_defconfig @@ -6,5 +6,6 @@ CONFIG_CMD_I2C=y CONFIG_CMD_DHCP=y CONFIG_CMD_MII=y CONFIG_CMD_PING=y +CONFIG_SYS_I2C_DW=y CONFIG_NETDEVICES=y CONFIG_ETH_DESIGNWARE=y diff --git a/configs/spear310_usbtty_defconfig b/configs/spear310_usbtty_defconfig index c0d8edffea..8edbe0c257 100644 --- a/configs/spear310_usbtty_defconfig +++ b/configs/spear310_usbtty_defconfig @@ -6,5 +6,6 @@ CONFIG_CMD_I2C=y CONFIG_CMD_DHCP=y CONFIG_CMD_MII=y CONFIG_CMD_PING=y +CONFIG_SYS_I2C_DW=y CONFIG_NETDEVICES=y CONFIG_ETH_DESIGNWARE=y diff --git a/configs/spear310_usbtty_nand_defconfig b/configs/spear310_usbtty_nand_defconfig index e9d14cec14..b622f742db 100644 --- a/configs/spear310_usbtty_nand_defconfig +++ b/configs/spear310_usbtty_nand_defconfig @@ -6,5 +6,6 @@ CONFIG_CMD_I2C=y CONFIG_CMD_DHCP=y CONFIG_CMD_MII=y CONFIG_CMD_PING=y +CONFIG_SYS_I2C_DW=y CONFIG_NETDEVICES=y CONFIG_ETH_DESIGNWARE=y diff --git a/configs/spear310_usbtty_pnor_defconfig b/configs/spear310_usbtty_pnor_defconfig index 2e46e64183..241a72acf5 100644 --- a/configs/spear310_usbtty_pnor_defconfig +++ b/configs/spear310_usbtty_pnor_defconfig @@ -6,5 +6,6 @@ CONFIG_CMD_I2C=y CONFIG_CMD_DHCP=y CONFIG_CMD_MII=y CONFIG_CMD_PING=y +CONFIG_SYS_I2C_DW=y CONFIG_NETDEVICES=y CONFIG_ETH_DESIGNWARE=y diff --git a/configs/spear320_defconfig b/configs/spear320_defconfig index 8dba79ad84..49d7c04395 100644 --- a/configs/spear320_defconfig +++ b/configs/spear320_defconfig @@ -6,5 +6,6 @@ CONFIG_CMD_I2C=y CONFIG_CMD_DHCP=y CONFIG_CMD_MII=y CONFIG_CMD_PING=y +CONFIG_SYS_I2C_DW=y CONFIG_NETDEVICES=y CONFIG_ETH_DESIGNWARE=y diff --git a/configs/spear320_nand_defconfig b/configs/spear320_nand_defconfig index 7f33c78fed..70b3025fc5 100644 --- a/configs/spear320_nand_defconfig +++ b/configs/spear320_nand_defconfig @@ -6,5 +6,6 @@ CONFIG_CMD_I2C=y CONFIG_CMD_DHCP=y CONFIG_CMD_MII=y CONFIG_CMD_PING=y +CONFIG_SYS_I2C_DW=y CONFIG_NETDEVICES=y CONFIG_ETH_DESIGNWARE=y diff --git a/configs/spear320_pnor_defconfig b/configs/spear320_pnor_defconfig index f7d37253e0..5ced0e17bd 100644 --- a/configs/spear320_pnor_defconfig +++ b/configs/spear320_pnor_defconfig @@ -6,5 +6,6 @@ CONFIG_CMD_I2C=y CONFIG_CMD_DHCP=y CONFIG_CMD_MII=y CONFIG_CMD_PING=y +CONFIG_SYS_I2C_DW=y CONFIG_NETDEVICES=y CONFIG_ETH_DESIGNWARE=y diff --git a/configs/spear320_usbtty_defconfig b/configs/spear320_usbtty_defconfig index 9e4125374d..de75b17df5 100644 --- a/configs/spear320_usbtty_defconfig +++ b/configs/spear320_usbtty_defconfig @@ -6,5 +6,6 @@ CONFIG_CMD_I2C=y CONFIG_CMD_DHCP=y CONFIG_CMD_MII=y CONFIG_CMD_PING=y +CONFIG_SYS_I2C_DW=y CONFIG_NETDEVICES=y CONFIG_ETH_DESIGNWARE=y diff --git a/configs/spear320_usbtty_nand_defconfig b/configs/spear320_usbtty_nand_defconfig index e61c74e5b3..2202d2eaf4 100644 --- a/configs/spear320_usbtty_nand_defconfig +++ b/configs/spear320_usbtty_nand_defconfig @@ -6,5 +6,6 @@ CONFIG_CMD_I2C=y CONFIG_CMD_DHCP=y CONFIG_CMD_MII=y CONFIG_CMD_PING=y +CONFIG_SYS_I2C_DW=y CONFIG_NETDEVICES=y CONFIG_ETH_DESIGNWARE=y diff --git a/configs/spear320_usbtty_pnor_defconfig b/configs/spear320_usbtty_pnor_defconfig index 741009349a..35bb0364af 100644 --- a/configs/spear320_usbtty_pnor_defconfig +++ b/configs/spear320_usbtty_pnor_defconfig @@ -6,5 +6,6 @@ CONFIG_CMD_I2C=y CONFIG_CMD_DHCP=y CONFIG_CMD_MII=y CONFIG_CMD_PING=y +CONFIG_SYS_I2C_DW=y CONFIG_NETDEVICES=y CONFIG_ETH_DESIGNWARE=y diff --git a/configs/spear600_defconfig b/configs/spear600_defconfig index f0e041fdda..f54083984b 100644 --- a/configs/spear600_defconfig +++ b/configs/spear600_defconfig @@ -9,5 +9,6 @@ CONFIG_CMD_I2C=y CONFIG_CMD_DHCP=y CONFIG_CMD_MII=y CONFIG_CMD_PING=y +CONFIG_SYS_I2C_DW=y CONFIG_NETDEVICES=y CONFIG_ETH_DESIGNWARE=y diff --git a/configs/spear600_nand_defconfig b/configs/spear600_nand_defconfig index cc4067d1c3..de416d91a8 100644 --- a/configs/spear600_nand_defconfig +++ b/configs/spear600_nand_defconfig @@ -6,5 +6,6 @@ CONFIG_CMD_I2C=y CONFIG_CMD_DHCP=y CONFIG_CMD_MII=y CONFIG_CMD_PING=y +CONFIG_SYS_I2C_DW=y CONFIG_NETDEVICES=y CONFIG_ETH_DESIGNWARE=y diff --git a/configs/spear600_usbtty_defconfig b/configs/spear600_usbtty_defconfig index df21355777..8b6e0d0acd 100644 --- a/configs/spear600_usbtty_defconfig +++ b/configs/spear600_usbtty_defconfig @@ -6,5 +6,6 @@ CONFIG_CMD_I2C=y CONFIG_CMD_DHCP=y CONFIG_CMD_MII=y CONFIG_CMD_PING=y +CONFIG_SYS_I2C_DW=y CONFIG_NETDEVICES=y CONFIG_ETH_DESIGNWARE=y diff --git a/configs/spear600_usbtty_nand_defconfig b/configs/spear600_usbtty_nand_defconfig index 48140aa467..e8b4b0a659 100644 --- a/configs/spear600_usbtty_nand_defconfig +++ b/configs/spear600_usbtty_nand_defconfig @@ -6,5 +6,6 @@ CONFIG_CMD_I2C=y CONFIG_CMD_DHCP=y CONFIG_CMD_MII=y CONFIG_CMD_PING=y +CONFIG_SYS_I2C_DW=y CONFIG_NETDEVICES=y CONFIG_ETH_DESIGNWARE=y diff --git a/configs/x600_defconfig b/configs/x600_defconfig index 1a07b9d536..ace620ba3a 100644 --- a/configs/x600_defconfig +++ b/configs/x600_defconfig @@ -17,6 +17,7 @@ CONFIG_CMD_PING=y CONFIG_CMD_CACHE=y CONFIG_CMD_FAT=y CONFIG_CMD_FS_GENERIC=y +CONFIG_SYS_I2C_DW=y CONFIG_NETDEVICES=y CONFIG_ETH_DESIGNWARE=y CONFIG_USE_TINY_PRINTF=y diff --git a/include/configs/axs101.h b/include/configs/axs101.h index 1bd472969f..05d2d45b25 100644 --- a/include/configs/axs101.h +++ b/include/configs/axs101.h @@ -59,7 +59,6 @@ * I2C configuration */ #define CONFIG_SYS_I2C -#define CONFIG_SYS_I2C_DW #define CONFIG_I2C_ENV_EEPROM_BUS 2 #define CONFIG_SYS_I2C_SPEED 100000 #define CONFIG_SYS_I2C_SPEED1 100000 diff --git a/include/configs/socfpga_common.h b/include/configs/socfpga_common.h index 4fdc09a3ce..f6577668a1 100644 --- a/include/configs/socfpga_common.h +++ b/include/configs/socfpga_common.h @@ -173,7 +173,6 @@ * I2C support */ #define CONFIG_SYS_I2C -#define CONFIG_SYS_I2C_DW #define CONFIG_SYS_I2C_BUS_MAX 4 #define CONFIG_SYS_I2C_BASE SOCFPGA_I2C0_ADDRESS #define CONFIG_SYS_I2C_BASE1 SOCFPGA_I2C1_ADDRESS diff --git a/include/configs/spear-common.h b/include/configs/spear-common.h index c4b6234096..7b2d262b4b 100644 --- a/include/configs/spear-common.h +++ b/include/configs/spear-common.h @@ -35,7 +35,6 @@ /* I2C driver configuration */ #define CONFIG_SYS_I2C -#define CONFIG_SYS_I2C_DW #if defined(CONFIG_SPEAR600) #define CONFIG_SYS_I2C_BASE 0xD0200000 #elif defined(CONFIG_SPEAR300) diff --git a/include/configs/x600.h b/include/configs/x600.h index d7da0b295b..5fdd2bee04 100644 --- a/include/configs/x600.h +++ b/include/configs/x600.h @@ -85,7 +85,6 @@ /* I2C config options */ #define CONFIG_SYS_I2C -#define CONFIG_SYS_I2C_DW #define CONFIG_SYS_I2C_BASE 0xD0200000 #define CONFIG_SYS_I2C_SPEED 400000 #define CONFIG_SYS_I2C_SLAVE 0x02 From 3a3705280d1d06e4d9a62fbe895dbe03939ad00e Mon Sep 17 00:00:00 2001 From: Stefan Roese Date: Thu, 28 Apr 2016 09:47:19 +0200 Subject: [PATCH 017/162] i2c: Select SYS_I2C_DW_ENABLE_STATUS_UNSUPPORTED for SPEAr The DW I2C controller in the SPEAr SoCs doesn't support the enable status register check. This patch selects SYS_I2C_DW_ENABLE_STATUS_UNSUPPORTED for these boards. Signed-off-by: Stefan Roese Cc: Heiko Schocher --- drivers/i2c/Kconfig | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/i2c/Kconfig b/drivers/i2c/Kconfig index 193b9f59b8..6e22bbadff 100644 --- a/drivers/i2c/Kconfig +++ b/drivers/i2c/Kconfig @@ -80,6 +80,16 @@ config SYS_I2C_DW controller is used in various SoCs, e.g. the ST SPEAr, Altera SoCFPGA, Synopsys ARC700 and some Intel x86 SoCs. +config SYS_I2C_DW_ENABLE_STATUS_UNSUPPORTED + bool "DW I2C Enable Status Register not supported" + depends on SYS_I2C_DW && (TARGET_SPEAR300 || TARGET_SPEAR310 || \ + TARGET_SPEAR320 || TARGET_SPEAR600 || TARGET_X600) + default y + help + Some versions of the Designware I2C controller do not support the + enable status register. This config option can be enabled in such + cases. + config SYS_I2C_INTEL bool "Intel I2C/SMBUS driver" depends on DM_I2C From d6b7757e41d22e08f21f58d3fe9183a150582f61 Mon Sep 17 00:00:00 2001 From: Chris Packham Date: Fri, 13 May 2016 15:19:31 +1200 Subject: [PATCH 018/162] i2c: mvtwsi: Eliminate twsi_control_flags In a system where the initial u-boot location is genuinely NOR flash (as opposed to RAM or a cache-line setup by a pre-bootloader) writes to the data section are problematic. At best these writes have no effect, at worst they put the flash memory into a status mode which changes the executable code underneath us. Pass around a stack variable from the top of the twsi i2c driver to avoid writing to global data. Signed-off-by: Chris Packham --- drivers/i2c/mvtwsi.c | 62 +++++++++++++++++++++----------------------- 1 file changed, 29 insertions(+), 33 deletions(-) diff --git a/drivers/i2c/mvtwsi.c b/drivers/i2c/mvtwsi.c index 221ff4fe7a..bf4443287f 100644 --- a/drivers/i2c/mvtwsi.c +++ b/drivers/i2c/mvtwsi.c @@ -184,27 +184,18 @@ static int twsi_wait(struct i2c_adapter *adap, int expected_status) MVTWSI_ERROR_TIMEOUT, control, status, expected_status); } -/* - * These flags are ORed to any write to the control register - * They allow global setting of TWSIEN and ACK. - * By default none are set. - * twsi_start() sets TWSIEN (in case the controller was disabled) - * twsi_recv() sets ACK or resets it depending on expected status. - */ -static u8 twsi_control_flags = MVTWSI_CONTROL_TWSIEN; - /* * Assert the START condition, either in a single I2C transaction * or inside back-to-back ones (repeated starts). */ -static int twsi_start(struct i2c_adapter *adap, int expected_status) +static int twsi_start(struct i2c_adapter *adap, int expected_status, u8 *flags) { struct mvtwsi_registers *twsi = twsi_get_base(adap); /* globally set TWSIEN in case it was not */ - twsi_control_flags |= MVTWSI_CONTROL_TWSIEN; + *flags |= MVTWSI_CONTROL_TWSIEN; /* assert START */ - writel(twsi_control_flags | MVTWSI_CONTROL_START | + writel(*flags | MVTWSI_CONTROL_START | MVTWSI_CONTROL_CLEAR_IFLG, &twsi->control); /* wait for controller to process START */ return twsi_wait(adap, expected_status); @@ -213,14 +204,15 @@ static int twsi_start(struct i2c_adapter *adap, int expected_status) /* * Send a byte (i2c address or data). */ -static int twsi_send(struct i2c_adapter *adap, u8 byte, int expected_status) +static int twsi_send(struct i2c_adapter *adap, u8 byte, int expected_status, + u8 *flags) { struct mvtwsi_registers *twsi = twsi_get_base(adap); /* put byte in data register for sending */ writel(byte, &twsi->data); /* clear any pending interrupt -- that'll cause sending */ - writel(twsi_control_flags | MVTWSI_CONTROL_CLEAR_IFLG, &twsi->control); + writel(*flags | MVTWSI_CONTROL_CLEAR_IFLG, &twsi->control); /* wait for controller to receive byte and check ACK */ return twsi_wait(adap, expected_status); } @@ -229,18 +221,18 @@ static int twsi_send(struct i2c_adapter *adap, u8 byte, int expected_status) * Receive a byte. * Global mvtwsi_control_flags variable says if we should ack or nak. */ -static int twsi_recv(struct i2c_adapter *adap, u8 *byte) +static int twsi_recv(struct i2c_adapter *adap, u8 *byte, u8 *flags) { struct mvtwsi_registers *twsi = twsi_get_base(adap); int expected_status, status; /* compute expected status based on ACK bit in global control flags */ - if (twsi_control_flags & MVTWSI_CONTROL_ACK) + if (*flags & MVTWSI_CONTROL_ACK) expected_status = MVTWSI_STATUS_DATA_R_ACK; else expected_status = MVTWSI_STATUS_DATA_R_NAK; /* acknowledge *previous state* and launch receive */ - writel(twsi_control_flags | MVTWSI_CONTROL_CLEAR_IFLG, &twsi->control); + writel(*flags | MVTWSI_CONTROL_CLEAR_IFLG, &twsi->control); /* wait for controller to receive byte and assert ACK or NAK */ status = twsi_wait(adap, expected_status); /* if we did receive expected byte then store it */ @@ -296,8 +288,7 @@ static unsigned int twsi_calc_freq(const int n, const int m) static void twsi_reset(struct i2c_adapter *adap) { struct mvtwsi_registers *twsi = twsi_get_base(adap); - /* ensure controller will be enabled by any twsi*() function */ - twsi_control_flags = MVTWSI_CONTROL_TWSIEN; + /* reset controller */ writel(0, &twsi->soft_reset); /* wait 2 ms -- this is what the Marvell LSP does */ @@ -353,7 +344,7 @@ static void twsi_i2c_init(struct i2c_adapter *adap, int speed, int slaveadd) * Expected address status will derive from direction bit (bit 0) in addr. */ static int i2c_begin(struct i2c_adapter *adap, int expected_start_status, - u8 addr) + u8 addr, u8 *flags) { int status, expected_addr_status; @@ -363,10 +354,11 @@ static int i2c_begin(struct i2c_adapter *adap, int expected_start_status, else /* writing */ expected_addr_status = MVTWSI_STATUS_ADDR_W_ACK; /* assert START */ - status = twsi_start(adap, expected_start_status); + status = twsi_start(adap, expected_start_status, flags); /* send out the address if the start went well */ if (status == 0) - status = twsi_send(adap, addr, expected_addr_status); + status = twsi_send(adap, addr, expected_addr_status, + flags); /* return ok or status of first failure to caller */ return status; } @@ -378,13 +370,14 @@ static int i2c_begin(struct i2c_adapter *adap, int expected_start_status, static int twsi_i2c_probe(struct i2c_adapter *adap, uchar chip) { u8 dummy_byte; + u8 flags = 0; int status; /* begin i2c read */ - status = i2c_begin(adap, MVTWSI_STATUS_START, (chip << 1) | 1); + status = i2c_begin(adap, MVTWSI_STATUS_START, (chip << 1) | 1, &flags); /* dummy read was accepted: receive byte but NAK it. */ if (status == 0) - status = twsi_recv(adap, &dummy_byte); + status = twsi_recv(adap, &dummy_byte, &flags); /* Stop transaction */ twsi_stop(adap, 0); /* return 0 or status of first failure */ @@ -405,27 +398,28 @@ static int twsi_i2c_read(struct i2c_adapter *adap, uchar chip, uint addr, int alen, uchar *data, int length) { int status; + u8 flags = 0; /* begin i2c write to send the address bytes */ - status = i2c_begin(adap, MVTWSI_STATUS_START, (chip << 1)); + status = i2c_begin(adap, MVTWSI_STATUS_START, (chip << 1), &flags); /* send addr bytes */ while ((status == 0) && alen--) status = twsi_send(adap, addr >> (8*alen), - MVTWSI_STATUS_DATA_W_ACK); + MVTWSI_STATUS_DATA_W_ACK, &flags); /* begin i2c read to receive eeprom data bytes */ if (status == 0) status = i2c_begin(adap, MVTWSI_STATUS_REPEATED_START, - (chip << 1) | 1); + (chip << 1) | 1, &flags); /* prepare ACK if at least one byte must be received */ if (length > 0) - twsi_control_flags |= MVTWSI_CONTROL_ACK; + flags |= MVTWSI_CONTROL_ACK; /* now receive actual bytes */ while ((status == 0) && length--) { /* reset NAK if we if no more to read now */ if (length == 0) - twsi_control_flags &= ~MVTWSI_CONTROL_ACK; + flags &= ~MVTWSI_CONTROL_ACK; /* read current byte */ - status = twsi_recv(adap, data++); + status = twsi_recv(adap, data++, &flags); } /* Stop transaction */ status = twsi_stop(adap, status); @@ -441,16 +435,18 @@ static int twsi_i2c_write(struct i2c_adapter *adap, uchar chip, uint addr, int alen, uchar *data, int length) { int status; + u8 flags = 0; /* begin i2c write to send the eeprom adress bytes then data bytes */ - status = i2c_begin(adap, MVTWSI_STATUS_START, (chip << 1)); + status = i2c_begin(adap, MVTWSI_STATUS_START, (chip << 1), &flags); /* send addr bytes */ while ((status == 0) && alen--) status = twsi_send(adap, addr >> (8*alen), - MVTWSI_STATUS_DATA_W_ACK); + MVTWSI_STATUS_DATA_W_ACK, &flags); /* send data bytes */ while ((status == 0) && (length-- > 0)) - status = twsi_send(adap, *(data++), MVTWSI_STATUS_DATA_W_ACK); + status = twsi_send(adap, *(data++), MVTWSI_STATUS_DATA_W_ACK, + &flags); /* Stop transaction */ status = twsi_stop(adap, status); /* return 0 or status of first failure */ From 037734393ef6181e87d85be15468af4baee70b42 Mon Sep 17 00:00:00 2001 From: Peng Fan Date: Thu, 14 Apr 2016 21:45:06 +0800 Subject: [PATCH 019/162] dm: gpio: pca953x: introduce driver model support for pca953x Introduce a new driver that supports driver model for pca953x. The pca953x chips are used as I2C I/O expanders. This driver is designed to support the following chips: " 4 bits: pca9536, pca9537 8 bits: max7310, max7315, pca6107, pca9534, pca9538, pca9554, pca9556, pca9557, pca9574, tca6408, xra1202 16 bits: max7312, max7313, pca9535, pca9539, pca9555, pca9575, tca6416 24 bits: tca6424 40 bits: pca9505, pca9698 " But for now this driver only supports max 24 bits and pca953x compatible chips. pca957x compatible chips are not supported now. These can be addressed when we need to add such support for the different chips. This driver has been tested on i.MX6 SoloX Sabreauto board with max7310 i2c expander using gpio command as following: =>gpio status -a Bank gpio@30_: gpio@30_0: input: 1 [ ] => dm tree: i2c [ ] | | `-- i2c@021a8000 gpio [ ] | | |-- gpio@30 gpio [ ] | | `-- gpio@32 Signed-off-by: Peng Fan Cc: Simon Glass Cc: Masahiro Yamada Cc: Wenyou Yang Cc: Daniel Schwierzeck Cc: Purna Chandra Mandal Cc: Thomas Chou Cc: Bhuvanchandra DV Cc: Andrea Scian Cc: Michal Simek Cc: Stefano Babic Cc: Fabio Estevam Acked-by: Simon Glass Tested-by: Michal Simek #on ZynqMP zcu102 --- drivers/gpio/Kconfig | 22 +++ drivers/gpio/Makefile | 2 + drivers/gpio/pca953x_gpio.c | 351 ++++++++++++++++++++++++++++++++++++ 3 files changed, 375 insertions(+) create mode 100644 drivers/gpio/pca953x_gpio.c diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 2b4624d7f8..e6337c24d8 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -143,4 +143,26 @@ config ZYNQ_GPIO help Supports GPIO access on Zynq SoC. +config DM_PCA953X + bool "PCA95[357]x, PCA9698, TCA64xx, and MAX7310 I/O ports" + depends on DM_GPIO + help + Say yes here to provide access to several register-oriented + SMBus I/O expanders, made mostly by NXP or TI. Compatible + models include: + + 4 bits: pca9536, pca9537 + + 8 bits: max7310, max7315, pca6107, pca9534, pca9538, pca9554, + pca9556, pca9557, pca9574, tca6408, xra1202 + + 16 bits: max7312, max7313, pca9535, pca9539, pca9555, pca9575, + tca6416 + + 24 bits: tca6424 + + 40 bits: pca9505, pca9698 + + Now, max 24 bits chips and PCA953X compatible chips are + supported endmenu diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index 4f071c4517..4b1f6b9301 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -11,6 +11,8 @@ obj-$(CONFIG_AXP_GPIO) += axp_gpio.o endif obj-$(CONFIG_DM_GPIO) += gpio-uclass.o +obj-$(CONFIG_DM_PCA953X) += pca953x_gpio.o + obj-$(CONFIG_AT91_GPIO) += at91_gpio.o obj-$(CONFIG_ATMEL_PIO4) += atmel_pio4.o obj-$(CONFIG_INTEL_ICH6_GPIO) += intel_ich6_gpio.o diff --git a/drivers/gpio/pca953x_gpio.c b/drivers/gpio/pca953x_gpio.c new file mode 100644 index 0000000000..987d10e967 --- /dev/null +++ b/drivers/gpio/pca953x_gpio.c @@ -0,0 +1,351 @@ +/* + * Take linux kernel driver drivers/gpio/gpio-pca953x.c for reference. + * + * Copyright (C) 2016 Peng Fan + * + * SPDX-License-Identifier: GPL-2.0+ + * + */ + +/* + * Note: + * The driver's compatible table is borrowed from Linux Kernel, + * but now max supported gpio pins is 24 and only PCA953X_TYPE + * is supported. PCA957X_TYPE is not supported now. + * Also the Polarity Inversion feature is not supported now. + * + * TODO: + * 1. Support PCA957X_TYPE + * 2. Support max 40 gpio pins + * 3. Support Plolarity Inversion + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define PCA953X_INPUT 0 +#define PCA953X_OUTPUT 1 +#define PCA953X_INVERT 2 +#define PCA953X_DIRECTION 3 + +#define PCA_GPIO_MASK 0x00FF +#define PCA_INT 0x0100 +#define PCA953X_TYPE 0x1000 +#define PCA957X_TYPE 0x2000 +#define PCA_TYPE_MASK 0xF000 +#define PCA_CHIP_TYPE(x) ((x) & PCA_TYPE_MASK) + +enum { + PCA953X_DIRECTION_IN, + PCA953X_DIRECTION_OUT, +}; + +#define MAX_BANK 3 +#define BANK_SZ 8 + +DECLARE_GLOBAL_DATA_PTR; + +/* + * struct pca953x_info - Data for pca953x + * + * @dev: udevice structure for the device + * @addr: i2c slave address + * @invert: Polarity inversion or not + * @gpio_count: the number of gpio pins that the device supports + * @chip_type: indicate the chip type,PCA953X or PCA957X + * @bank_count: the number of banks that the device supports + * @reg_output: array to hold the value of output registers + * @reg_direction: array to hold the value of direction registers + */ +struct pca953x_info { + struct udevice *dev; + int addr; + int invert; + int gpio_count; + int chip_type; + int bank_count; + u8 reg_output[MAX_BANK]; + u8 reg_direction[MAX_BANK]; +}; + +static int pca953x_write_single(struct udevice *dev, int reg, u8 val, + int offset) +{ + struct pca953x_info *info = dev_get_platdata(dev); + int bank_shift = fls((info->gpio_count - 1) / BANK_SZ); + int off = offset / BANK_SZ; + int ret = 0; + + ret = dm_i2c_write(dev, (reg << bank_shift) + off, &val, 1); + if (ret) { + dev_err(dev, "%s error\n", __func__); + return ret; + } + + return 0; +} + +static int pca953x_read_single(struct udevice *dev, int reg, u8 *val, + int offset) +{ + struct pca953x_info *info = dev_get_platdata(dev); + int bank_shift = fls((info->gpio_count - 1) / BANK_SZ); + int off = offset / BANK_SZ; + int ret; + u8 byte; + + ret = dm_i2c_read(dev, (reg << bank_shift) + off, &byte, 1); + if (ret) { + dev_err(dev, "%s error\n", __func__); + return ret; + } + + *val = byte; + + return 0; +} + +static int pca953x_read_regs(struct udevice *dev, int reg, u8 *val) +{ + struct pca953x_info *info = dev_get_platdata(dev); + int ret = 0; + + if (info->gpio_count <= 8) { + ret = dm_i2c_read(dev, reg, val, 1); + } else if (info->gpio_count <= 16) { + ret = dm_i2c_read(dev, reg << 1, val, info->bank_count); + } else { + dev_err(dev, "Unsupported now\n"); + return -EINVAL; + } + + return ret; +} + +static int pca953x_is_output(struct udevice *dev, int offset) +{ + struct pca953x_info *info = dev_get_platdata(dev); + + int bank = offset / BANK_SZ; + int off = offset % BANK_SZ; + + /*0: output; 1: input */ + return !(info->reg_direction[bank] & (1 << off)); +} + +static int pca953x_get_value(struct udevice *dev, unsigned offset) +{ + int ret; + u8 val = 0; + + ret = pca953x_read_single(dev, PCA953X_INPUT, &val, offset); + if (ret) + return ret; + + return (val >> offset) & 0x1; +} + +static int pca953x_set_value(struct udevice *dev, unsigned offset, + int value) +{ + struct pca953x_info *info = dev_get_platdata(dev); + int bank = offset / BANK_SZ; + int off = offset % BANK_SZ; + u8 val; + int ret; + + if (value) + val = info->reg_output[bank] | (1 << off); + else + val = info->reg_output[bank] & ~(1 << off); + + ret = pca953x_write_single(dev, PCA953X_OUTPUT, val, offset); + if (ret) + return ret; + + info->reg_output[bank] = val; + + return 0; +} + +static int pca953x_set_direction(struct udevice *dev, unsigned offset, int dir) +{ + struct pca953x_info *info = dev_get_platdata(dev); + int bank = offset / BANK_SZ; + int off = offset % BANK_SZ; + u8 val; + int ret; + + if (dir == PCA953X_DIRECTION_IN) + val = info->reg_direction[bank] | (1 << off); + else + val = info->reg_direction[bank] & ~(1 << off); + + ret = pca953x_write_single(dev, PCA953X_DIRECTION, val, offset); + if (ret) + return ret; + + info->reg_direction[bank] = val; + + return 0; +} + +static int pca953x_direction_input(struct udevice *dev, unsigned offset) +{ + return pca953x_set_direction(dev, offset, PCA953X_DIRECTION_IN); +} + +static int pca953x_direction_output(struct udevice *dev, unsigned offset, + int value) +{ + /* Configure output value. */ + pca953x_set_value(dev, offset, value); + + /* Configure direction as output. */ + pca953x_set_direction(dev, offset, PCA953X_DIRECTION_OUT); + + return 0; +} + +static int pca953x_get_function(struct udevice *dev, unsigned offset) +{ + if (pca953x_is_output(dev, offset)) + return GPIOF_OUTPUT; + else + return GPIOF_INPUT; +} + +static int pca953x_xlate(struct udevice *dev, struct gpio_desc *desc, + struct fdtdec_phandle_args *args) +{ + desc->offset = args->args[0]; + desc->flags = args->args[1] & GPIO_ACTIVE_LOW ? GPIOD_ACTIVE_LOW : 0; + + return 0; +} + +static const struct dm_gpio_ops pca953x_ops = { + .direction_input = pca953x_direction_input, + .direction_output = pca953x_direction_output, + .get_value = pca953x_get_value, + .set_value = pca953x_set_value, + .get_function = pca953x_get_function, + .xlate = pca953x_xlate, +}; + +static int pca953x_probe(struct udevice *dev) +{ + struct pca953x_info *info = dev_get_platdata(dev); + struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev); + struct dm_i2c_chip *chip = dev_get_parent_platdata(dev); + char name[32], *str; + int addr; + ulong driver_data; + int ret; + + if (!info) { + dev_err(dev, "platdata not ready\n"); + return -ENOMEM; + } + + if (!chip) { + dev_err(dev, "i2c not ready\n"); + return -ENODEV; + } + + addr = fdtdec_get_int(gd->fdt_blob, dev->of_offset, "reg", 0); + if (addr == 0) + return -ENODEV; + + info->addr = addr; + + driver_data = dev_get_driver_data(dev); + + info->gpio_count = driver_data & PCA_GPIO_MASK; + if (info->gpio_count > MAX_BANK * BANK_SZ) { + dev_err(dev, "Max support %d pins now\n", MAX_BANK * BANK_SZ); + return -EINVAL; + } + + info->chip_type = PCA_CHIP_TYPE(driver_data); + if (info->chip_type != PCA953X_TYPE) { + dev_err(dev, "Only support PCA953X chip type now.\n"); + return -EINVAL; + } + + info->bank_count = DIV_ROUND_UP(info->gpio_count, BANK_SZ); + + ret = pca953x_read_regs(dev, PCA953X_OUTPUT, info->reg_output); + if (ret) { + dev_err(dev, "Error reading output register\n"); + return ret; + } + + ret = pca953x_read_regs(dev, PCA953X_DIRECTION, info->reg_direction); + if (ret) { + dev_err(dev, "Error reading direction register\n"); + return ret; + } + + snprintf(name, sizeof(name), "gpio@%x_", info->addr); + str = strdup(name); + if (!str) + return -ENOMEM; + uc_priv->bank_name = str; + uc_priv->gpio_count = info->gpio_count; + + dev_dbg(dev, "%s is ready\n", str); + + return 0; +} + +#define OF_953X(__nrgpio, __int) (ulong)(__nrgpio | PCA953X_TYPE | __int) +#define OF_957X(__nrgpio, __int) (ulong)(__nrgpio | PCA957X_TYPE | __int) + +static const struct udevice_id pca953x_ids[] = { + { .compatible = "nxp,pca9505", .data = OF_953X(40, PCA_INT), }, + { .compatible = "nxp,pca9534", .data = OF_953X(8, PCA_INT), }, + { .compatible = "nxp,pca9535", .data = OF_953X(16, PCA_INT), }, + { .compatible = "nxp,pca9536", .data = OF_953X(4, 0), }, + { .compatible = "nxp,pca9537", .data = OF_953X(4, PCA_INT), }, + { .compatible = "nxp,pca9538", .data = OF_953X(8, PCA_INT), }, + { .compatible = "nxp,pca9539", .data = OF_953X(16, PCA_INT), }, + { .compatible = "nxp,pca9554", .data = OF_953X(8, PCA_INT), }, + { .compatible = "nxp,pca9555", .data = OF_953X(16, PCA_INT), }, + { .compatible = "nxp,pca9556", .data = OF_953X(8, 0), }, + { .compatible = "nxp,pca9557", .data = OF_953X(8, 0), }, + { .compatible = "nxp,pca9574", .data = OF_957X(8, PCA_INT), }, + { .compatible = "nxp,pca9575", .data = OF_957X(16, PCA_INT), }, + { .compatible = "nxp,pca9698", .data = OF_953X(40, 0), }, + + { .compatible = "maxim,max7310", .data = OF_953X(8, 0), }, + { .compatible = "maxim,max7312", .data = OF_953X(16, PCA_INT), }, + { .compatible = "maxim,max7313", .data = OF_953X(16, PCA_INT), }, + { .compatible = "maxim,max7315", .data = OF_953X(8, PCA_INT), }, + + { .compatible = "ti,pca6107", .data = OF_953X(8, PCA_INT), }, + { .compatible = "ti,tca6408", .data = OF_953X(8, PCA_INT), }, + { .compatible = "ti,tca6416", .data = OF_953X(16, PCA_INT), }, + { .compatible = "ti,tca6424", .data = OF_953X(24, PCA_INT), }, + + { .compatible = "onsemi,pca9654", .data = OF_953X(8, PCA_INT), }, + + { .compatible = "exar,xra1202", .data = OF_953X(8, 0), }, + { } +}; + +U_BOOT_DRIVER(pca953x) = { + .name = "pca953x", + .id = UCLASS_GPIO, + .ops = &pca953x_ops, + .probe = pca953x_probe, + .platdata_auto_alloc_size = sizeof(struct pca953x_info), + .of_match = pca953x_ids, +}; From 5044c9cc6c4dffb2959769a785663f46cb418461 Mon Sep 17 00:00:00 2001 From: "angelo@sysam.it" Date: Wed, 27 Apr 2016 21:50:44 +0200 Subject: [PATCH 020/162] m68k: add malloc memory for early malloc To use serial uclass and DM, CONFIG_SYS_MALLOC_F must be used. So CONFIG_SYS_GENERIC_GLOBAL_DATA has been undefined and call to board_init_f_mem() is added for all cpu's. Signed-off-by: Angelo Dureghello Acked-by: Simon Glass --- arch/m68k/cpu/mcf5227x/start.S | 25 ++++++++++++++++++++----- arch/m68k/cpu/mcf523x/start.S | 27 ++++++++++++++++++++++----- arch/m68k/cpu/mcf52x2/start.S | 26 ++++++++++++++++++++++---- arch/m68k/cpu/mcf530x/cpu_init.c | 2 +- arch/m68k/cpu/mcf530x/start.S | 27 +++++++++++++++++++-------- arch/m68k/cpu/mcf532x/start.S | 27 ++++++++++++++++++++++----- arch/m68k/cpu/mcf5445x/start.S | 27 ++++++++++++++++++++++----- arch/m68k/cpu/mcf547x_8x/start.S | 25 ++++++++++++++++++++----- arch/m68k/include/asm/config.h | 2 -- 9 files changed, 148 insertions(+), 40 deletions(-) diff --git a/arch/m68k/cpu/mcf5227x/start.S b/arch/m68k/cpu/mcf5227x/start.S index 23024f94c8..13c036f746 100644 --- a/arch/m68k/cpu/mcf5227x/start.S +++ b/arch/m68k/cpu/mcf5227x/start.S @@ -372,14 +372,29 @@ _start: move.l %d0, (%a1) move.l %d0, (%a2) - /* set stackpointer to end of internal ram to get some stackspace for - the first c-code */ - move.l #(CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_INIT_SP_OFFSET), %sp - clr.l %sp@- + /* put relocation table address to a5 */ + move.l #__got_start, %a5 - move.l #__got_start, %a5 /* put relocation table address to a5 */ + /* setup stack initially on top of internal static ram */ + move.l #(CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_INIT_RAM_SIZE), %sp + + /* + * if configured, malloc_f arena will be reserved first, + * then (and always) gd struct space will be reserved + */ + move.l %sp, -(%sp) + bsr board_init_f_alloc_reserve + + /* update stack and frame-pointers */ + move.l %d0, %sp + move.l %sp, %fp + + /* initialize reserved area */ + move.l %d0, -(%sp) + bsr board_init_f_init_reserve bsr cpu_init_f /* run low-level CPU init code (from flash) */ + clr.l %sp@- bsr board_init_f /* run low-level board init code (from flash) */ /* board_init_f() does not return */ diff --git a/arch/m68k/cpu/mcf523x/start.S b/arch/m68k/cpu/mcf523x/start.S index 1702f98ab1..3aa4dd61fa 100644 --- a/arch/m68k/cpu/mcf523x/start.S +++ b/arch/m68k/cpu/mcf523x/start.S @@ -134,17 +134,34 @@ _start: move.l %d0, (%a1) move.l %d0, (%a2) - /* set stackpointer to end of internal ram to get some stackspace for the - first c-code */ - move.l #(CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_INIT_SP_OFFSET), %sp - clr.l %sp@- + /* put relocation table address to a5 */ + move.l #__got_start, %a5 - move.l #__got_start, %a5 /* put relocation table address to a5 */ + /* setup stack initially on top of internal static ram */ + move.l #(CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_INIT_RAM_SIZE), %sp + + /* + * if configured, malloc_f arena will be reserved first, + * then (and always) gd struct space will be reserved + */ + move.l %sp, -(%sp) + move.l #board_init_f_alloc_reserve, %a1 + jsr (%a1) + + /* update stack and frame-pointers */ + move.l %d0, %sp + move.l %sp, %fp + + /* initialize reserved area */ + move.l %d0, -(%sp) + move.l #board_init_f_init_reserve, %a1 + jsr (%a1) /* run low-level CPU init code (from flash) */ move.l #cpu_init_f, %a1 jsr (%a1) /* run low-level board init code (from flash) */ + clr.l %sp@- move.l #board_init_f, %a1 jsr (%a1) diff --git a/arch/m68k/cpu/mcf52x2/start.S b/arch/m68k/cpu/mcf52x2/start.S index 4af691f5af..a048884f6c 100644 --- a/arch/m68k/cpu/mcf52x2/start.S +++ b/arch/m68k/cpu/mcf52x2/start.S @@ -192,16 +192,34 @@ _after_flashbar_copy: move.l %d0, (%a1) move.l %d0, (%a2) - /* set stackpointer to end of internal ram to get some stackspace for the first c-code */ - move.l #(CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_INIT_SP_OFFSET), %sp - clr.l %sp@- + /* put relocation table address to a5 */ + move.l #__got_start, %a5 - move.l #__got_start, %a5 /* put relocation table address to a5 */ + /* setup stack initially on top of internal static ram */ + move.l #(CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_INIT_RAM_SIZE), %sp + + /* + * if configured, malloc_f arena will be reserved first, + * then (and always) gd struct space will be reserved + */ + move.l %sp, -(%sp) + move.l #board_init_f_alloc_reserve, %a1 + jsr (%a1) + + /* update stack and frame-pointers */ + move.l %d0, %sp + move.l %sp, %fp + + /* initialize reserved area */ + move.l %d0, -(%sp) + move.l #board_init_f_init_reserve, %a1 + jsr (%a1) /* run low-level CPU init code (from flash) */ move.l #cpu_init_f, %a1 jsr (%a1) /* run low-level board init code (from flash) */ + clr.l %sp@- move.l #board_init_f, %a1 jsr (%a1) diff --git a/arch/m68k/cpu/mcf530x/cpu_init.c b/arch/m68k/cpu/mcf530x/cpu_init.c index 80dc23910e..b09eed8024 100644 --- a/arch/m68k/cpu/mcf530x/cpu_init.c +++ b/arch/m68k/cpu/mcf530x/cpu_init.c @@ -142,7 +142,7 @@ int cpu_init_r(void) return 0; } -void uart_port_conf(void) +void uart_port_conf(int port) { } diff --git a/arch/m68k/cpu/mcf530x/start.S b/arch/m68k/cpu/mcf530x/start.S index 097958afda..ca8bb32063 100644 --- a/arch/m68k/cpu/mcf530x/start.S +++ b/arch/m68k/cpu/mcf530x/start.S @@ -126,21 +126,32 @@ _start: move.l %d0, (%a1) move.l %d0, (%a2) - /* - * set stackpointer to internal sram end - 80 - * (global data struct size + some bytes) - * get some stackspace for the first c-code, - */ - move.l #(CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_INIT_SP_OFFSET), %sp - clr.l %sp@- - /* put relocation table address to a5 */ move.l #__got_start, %a5 + /* setup stack initially on top of internal static ram */ + move.l #(CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_INIT_RAM_SIZE), %sp + + /* + * if configured, malloc_f arena will be reserved first, + * then (and always) gd struct space will be reserved + */ + move.l %sp, -(%sp) + bsr board_init_f_alloc_reserve + + /* update stack and frame-pointers */ + move.l %d0, %sp + move.l %sp, %fp + + /* initialize reserved area */ + move.l %d0, -(%sp) + bsr board_init_f_init_reserve + /* run low-level CPU init code (from flash) */ bsr cpu_init_f /* run low-level board init code (from flash) */ + clr.l %sp@- bsr board_init_f /* board_init_f() does not return */ diff --git a/arch/m68k/cpu/mcf532x/start.S b/arch/m68k/cpu/mcf532x/start.S index 131ad6e392..f25bc541be 100644 --- a/arch/m68k/cpu/mcf532x/start.S +++ b/arch/m68k/cpu/mcf532x/start.S @@ -148,17 +148,34 @@ _start: move.l %d0, (%a1) move.l %d0, (%a2) - /* set stackpointer to end of internal ram to get some stackspace for the - first c-code */ - move.l #(CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_INIT_SP_OFFSET), %sp - clr.l %sp@- + /* put relocation table address to a5 */ + move.l #__got_start, %a5 - move.l #__got_start, %a5 /* put relocation table address to a5 */ + /* setup stack initially on top of internal static ram */ + move.l #(CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_INIT_RAM_SIZE), %sp + + /* + * if configured, malloc_f arena will be reserved first, + * then (and always) gd struct space will be reserved + */ + move.l %sp, -(%sp) + move.l #board_init_f_alloc_reserve, %a1 + jsr (%a1) + + /* update stack and frame-pointers */ + move.l %d0, %sp + move.l %sp, %fp + + /* initialize reserved area */ + move.l %d0, -(%sp) + move.l #board_init_f_init_reserve, %a1 + jsr (%a1) /* run low-level CPU init code (from flash) */ move.l #cpu_init_f, %a1 jsr (%a1) /* run low-level board init code (from flash) */ + clr.l %sp@- move.l #board_init_f, %a1 jsr (%a1) diff --git a/arch/m68k/cpu/mcf5445x/start.S b/arch/m68k/cpu/mcf5445x/start.S index f50f147a4f..ba38678be3 100644 --- a/arch/m68k/cpu/mcf5445x/start.S +++ b/arch/m68k/cpu/mcf5445x/start.S @@ -657,17 +657,34 @@ _start: movec %d0, %RAMBAR1 #endif - /* set stackpointer to end of internal ram to get some stackspace for - the first c-code */ - move.l #(CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_INIT_SP_OFFSET), %sp - clr.l %sp@- + /* put relocation table address to a5 */ + move.l #__got_start, %a5 - move.l #__got_start, %a5 /* put relocation table address to a5 */ + /* setup stack initially on top of internal static ram */ + move.l #(CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_INIT_RAM_SIZE), %sp + + /* + * if configured, malloc_f arena will be reserved first, + * then (and always) gd struct space will be reserved + */ + move.l %sp, -(%sp) + move.l #board_init_f_alloc_reserve, %a1 + jsr (%a1) + + /* update stack and frame-pointers */ + move.l %d0, %sp + move.l %sp, %fp + + /* initialize reserved area */ + move.l %d0, -(%sp) + move.l #board_init_f_init_reserve, %a1 + jsr (%a1) /* run low-level CPU init code (from flash) */ move.l #cpu_init_f, %a1 jsr (%a1) /* run low-level board init code (from flash) */ + clr.l %sp@- move.l #board_init_f, %a1 jsr (%a1) diff --git a/arch/m68k/cpu/mcf547x_8x/start.S b/arch/m68k/cpu/mcf547x_8x/start.S index 75de22d37c..9a87a0da23 100644 --- a/arch/m68k/cpu/mcf547x_8x/start.S +++ b/arch/m68k/cpu/mcf547x_8x/start.S @@ -141,14 +141,29 @@ _start: move.l %d0, (%a1) move.l %d0, (%a2) - /* set stackpointer to end of internal ram to get some stackspace for the - first c-code */ - move.l #(CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_INIT_SP_OFFSET), %sp - clr.l %sp@- + /* put relocation table address to a5 */ + move.l #__got_start, %a5 - move.l #__got_start, %a5 /* put relocation table address to a5 */ + /* setup stack initially on top of internal static ram */ + move.l #(CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_INIT_RAM_SIZE), %sp + + /* + * if configured, malloc_f arena will be reserved first, + * then (and always) gd struct space will be reserved + */ + move.l %sp, -(%sp) + bsr board_init_f_alloc_reserve + + /* update stack and frame-pointers */ + move.l %d0, %sp + move.l %sp, %fp + + /* initialize reserved area */ + move.l %d0, -(%sp) + bsr board_init_f_init_reserve jbsr cpu_init_f /* run low-level CPU init code (from flash) */ + clr.l %sp@- jbsr board_init_f /* run low-level board init code (from flash) */ /* board_init_f() does not return */ diff --git a/arch/m68k/include/asm/config.h b/arch/m68k/include/asm/config.h index e1458acd2c..9c4d3fb8fd 100644 --- a/arch/m68k/include/asm/config.h +++ b/arch/m68k/include/asm/config.h @@ -7,8 +7,6 @@ #ifndef _ASM_CONFIG_H_ #define _ASM_CONFIG_H_ -#define CONFIG_SYS_GENERIC_GLOBAL_DATA - #define CONFIG_NEEDS_MANUAL_RELOC #define CONFIG_LMB From e27802af54c2ff2d4d58e4bc217644b75c04ac4c Mon Sep 17 00:00:00 2001 From: "angelo@sysam.it" Date: Wed, 27 Apr 2016 21:51:13 +0200 Subject: [PATCH 021/162] m68k: add DM model serial driver Boards can now use DM serial driver, or still legacy mcf uart driver version. Signed-off-by: Angelo Dureghello Acked-by: Simon Glass --- drivers/serial/mcfuart.c | 188 ++++++++++++++++----- include/dm/platform_data/serial_coldfire.h | 23 +++ 2 files changed, 167 insertions(+), 44 deletions(-) create mode 100644 include/dm/platform_data/serial_coldfire.h diff --git a/drivers/serial/mcfuart.c b/drivers/serial/mcfuart.c index 407354fc4c..059cb0fc6e 100644 --- a/drivers/serial/mcfuart.c +++ b/drivers/serial/mcfuart.c @@ -2,6 +2,9 @@ * (C) Copyright 2004-2007 Freescale Semiconductor, Inc. * TsiChung Liew, Tsi-Chung.Liew@freescale.com. * + * Modified to add device model (DM) support + * (C) Copyright 2015 Angelo Dureghello + * * SPDX-License-Identifier: GPL-2.0+ */ @@ -11,9 +14,10 @@ */ #include +#include +#include #include #include - #include #include @@ -21,91 +25,110 @@ DECLARE_GLOBAL_DATA_PTR; extern void uart_port_conf(int port); -static int mcf_serial_init(void) +static int mcf_serial_init_common(uart_t *uart, int port_idx, int baudrate) { - volatile uart_t *uart; u32 counter; - uart = (volatile uart_t *)(CONFIG_SYS_UART_BASE); - - uart_port_conf(CONFIG_SYS_UART_PORT); + uart_port_conf(port_idx); /* write to SICR: SIM2 = uart mode,dcd does not affect rx */ - uart->ucr = UART_UCR_RESET_RX; - uart->ucr = UART_UCR_RESET_TX; - uart->ucr = UART_UCR_RESET_ERROR; - uart->ucr = UART_UCR_RESET_MR; + writeb(UART_UCR_RESET_RX, &uart->ucr); + writeb(UART_UCR_RESET_TX, &uart->ucr); + writeb(UART_UCR_RESET_ERROR, &uart->ucr); + writeb(UART_UCR_RESET_MR, &uart->ucr); __asm__("nop"); - uart->uimr = 0; + writeb(0, &uart->uimr); /* write to CSR: RX/TX baud rate from timers */ - uart->ucsr = (UART_UCSR_RCS_SYS_CLK | UART_UCSR_TCS_SYS_CLK); + writeb(UART_UCSR_RCS_SYS_CLK | UART_UCSR_TCS_SYS_CLK, &uart->ucsr); - uart->umr = (UART_UMR_BC_8 | UART_UMR_PM_NONE); - uart->umr = UART_UMR_SB_STOP_BITS_1; + writeb(UART_UMR_BC_8 | UART_UMR_PM_NONE, &uart->umr); + writeb(UART_UMR_SB_STOP_BITS_1, &uart->umr); /* Setting up BaudRate */ - counter = (u32) ((gd->bus_clk / 32) + (gd->baudrate / 2)); - counter = counter / gd->baudrate; + counter = (u32) ((gd->bus_clk / 32) + (baudrate / 2)); + counter = counter / baudrate; /* write to CTUR: divide counter upper byte */ - uart->ubg1 = (u8) ((counter & 0xff00) >> 8); + writeb((u8)((counter & 0xff00) >> 8), &uart->ubg1); /* write to CTLR: divide counter lower byte */ - uart->ubg2 = (u8) (counter & 0x00ff); + writeb((u8)(counter & 0x00ff), &uart->ubg2); - uart->ucr = (UART_UCR_RX_ENABLED | UART_UCR_TX_ENABLED); + writeb(UART_UCR_RX_ENABLED | UART_UCR_TX_ENABLED, &uart->ucr); return (0); } +static void mcf_serial_setbrg_common(uart_t *uart, int baudrate) +{ + u32 counter; + + /* Setting up BaudRate */ + counter = (u32) ((gd->bus_clk / 32) + (baudrate / 2)); + counter = counter / baudrate; + + /* write to CTUR: divide counter upper byte */ + writeb(((counter & 0xff00) >> 8), &uart->ubg1); + /* write to CTLR: divide counter lower byte */ + writeb((counter & 0x00ff), &uart->ubg2); + + writeb(UART_UCR_RESET_RX, &uart->ucr); + writeb(UART_UCR_RESET_TX, &uart->ucr); + + writeb(UART_UCR_RX_ENABLED | UART_UCR_TX_ENABLED, &uart->ucr); +} + +#ifndef CONFIG_DM_SERIAL + +static int mcf_serial_init(void) +{ + uart_t *uart_base; + int port_idx; + + uart_base = (uart_t *)CONFIG_SYS_UART_BASE; + port_idx = CONFIG_SYS_UART_PORT; + + return mcf_serial_init_common(uart_base, port_idx, gd->baudrate); +} + static void mcf_serial_putc(const char c) { - volatile uart_t *uart = (volatile uart_t *)(CONFIG_SYS_UART_BASE); + uart_t *uart = (uart_t *)CONFIG_SYS_UART_BASE; if (c == '\n') serial_putc('\r'); /* Wait for last character to go. */ - while (!(uart->usr & UART_USR_TXRDY)) ; + while (!(readb(&uart->usr) & UART_USR_TXRDY)) + ; - uart->utb = c; + writeb(c, &uart->utb); } static int mcf_serial_getc(void) { - volatile uart_t *uart = (volatile uart_t *)(CONFIG_SYS_UART_BASE); + uart_t *uart = (uart_t *)CONFIG_SYS_UART_BASE; /* Wait for a character to arrive. */ - while (!(uart->usr & UART_USR_RXRDY)) ; - return uart->urb; -} + while (!(readb(&uart->usr) & UART_USR_RXRDY)) + ; -static int mcf_serial_tstc(void) -{ - volatile uart_t *uart = (volatile uart_t *)(CONFIG_SYS_UART_BASE); - - return (uart->usr & UART_USR_RXRDY); + return readb(&uart->urb); } static void mcf_serial_setbrg(void) { - volatile uart_t *uart = (volatile uart_t *)(CONFIG_SYS_UART_BASE); - u32 counter; + uart_t *uart = (uart_t *)CONFIG_SYS_UART_BASE; - /* Setting up BaudRate */ - counter = (u32) ((gd->bus_clk / 32) + (gd->baudrate / 2)); - counter = counter / gd->baudrate; + mcf_serial_setbrg_common(uart, gd->baudrate); +} - /* write to CTUR: divide counter upper byte */ - uart->ubg1 = ((counter & 0xff00) >> 8); - /* write to CTLR: divide counter lower byte */ - uart->ubg2 = (counter & 0x00ff); +static int mcf_serial_tstc(void) +{ + uart_t *uart = (uart_t *)CONFIG_SYS_UART_BASE; - uart->ucr = UART_UCR_RESET_RX; - uart->ucr = UART_UCR_RESET_TX; - - uart->ucr = UART_UCR_RX_ENABLED | UART_UCR_TX_ENABLED; + return readb(&uart->usr) & UART_USR_RXRDY; } static struct serial_device mcf_serial_drv = { @@ -128,3 +151,80 @@ __weak struct serial_device *default_serial_console(void) { return &mcf_serial_drv; } + +#endif + +#ifdef CONFIG_DM_SERIAL + +static int coldfire_serial_probe(struct udevice *dev) +{ + struct coldfire_serial_platdata *plat = dev->platdata; + + return mcf_serial_init_common((uart_t *)plat->base, + plat->port, plat->baudrate); +} + +static int coldfire_serial_putc(struct udevice *dev, const char ch) +{ + struct coldfire_serial_platdata *plat = dev->platdata; + uart_t *uart = (uart_t *)plat->base; + + /* Wait for last character to go. */ + if (!(readb(&uart->usr) & UART_USR_TXRDY)) + return -EAGAIN; + + writeb(ch, &uart->utb); + + return 0; +} + +static int coldfire_serial_getc(struct udevice *dev) +{ + struct coldfire_serial_platdata *plat = dev->platdata; + uart_t *uart = (uart_t *)(plat->base); + + /* Wait for a character to arrive. */ + if (!(readb(&uart->usr) & UART_USR_RXRDY)) + return -EAGAIN; + + return readb(&uart->urb); +} + +int coldfire_serial_setbrg(struct udevice *dev, int baudrate) +{ + struct coldfire_serial_platdata *plat = dev->platdata; + uart_t *uart = (uart_t *)(plat->base); + + mcf_serial_setbrg_common(uart, baudrate); + + return 0; +} + +static int coldfire_serial_pending(struct udevice *dev, bool input) +{ + struct coldfire_serial_platdata *plat = dev->platdata; + uart_t *uart = (uart_t *)(plat->base); + + if (input) + return readb(&uart->usr) & UART_USR_RXRDY ? 1 : 0; + else + return readb(&uart->usr) & UART_USR_TXRDY ? 0 : 1; + + return 0; +} + +static const struct dm_serial_ops coldfire_serial_ops = { + .putc = coldfire_serial_putc, + .pending = coldfire_serial_pending, + .getc = coldfire_serial_getc, + .setbrg = coldfire_serial_setbrg, +}; + +U_BOOT_DRIVER(serial_coldfire) = { + .name = "serial_coldfire", + .id = UCLASS_SERIAL, + .probe = coldfire_serial_probe, + .ops = &coldfire_serial_ops, + .flags = DM_FLAG_PRE_RELOC, +}; +#endif diff --git a/include/dm/platform_data/serial_coldfire.h b/include/dm/platform_data/serial_coldfire.h new file mode 100644 index 0000000000..5d86456f1e --- /dev/null +++ b/include/dm/platform_data/serial_coldfire.h @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2015 Angelo Dureghello + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef __serial_coldfire_h +#define __serial_coldfire_h + +/* + * struct coldfire_serial_platdata - information about a coldfire port + * + * @base: Uart port base register address + * @port: Uart port index, for cpu with pinmux for uart / gpio + * baudrtatre: Uart port baudrate + */ +struct coldfire_serial_platdata { + unsigned long base; + int port; + int baudrate; +}; + +#endif /* __serial_coldfire_h */ From f79f1e0c0ea06de3af79094bc80be6e218b5f6ef Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Mon, 11 Apr 2016 10:48:44 -0600 Subject: [PATCH 022/162] buildman: allow more incremental building One use-case for buildman is to continually run it interactively after each small step in a large refactoring operation. This gives more immediate feedback than making a number of commits and then going back and testing them. For this to work well, buildman needs to be extremely fast. At present, a couple issues prevent it being as fast as it could be: 1) Each time buildman runs "make %_defconfig", it runs "make mrproper" first. This throws away all previous build results, requiring a from-scratch build. Optionally avoiding this would speed up the build, at the cost of potentially causing or missing some build issues. 2) A build tree is created per thread rather than per board. When a thread switches between building different boards, this often causes many files to be rebuilt due to changing config options. Using a separate build tree for each board would avoid this. This does put more strain on the system's disk cache, but it is worth it on my system at least. This commit adds two command-line options to implement the changes described above; -I ("--incremental") turns of "make mrproper" and -P ("--per-board-out-dir") creats a build directory per board rather than per thread. Tested: ./tools/buildman/buildman.py tegra ./tools/buildman/buildman.py -I -P tegra ./tools/buildman/buildman.py -b tegra_dev tegra ./tools/buildman/buildman.py -b tegra_dev -I -P tegra ... each once after deleting the buildman result/work directory, and once "incrementally" after a previous identical invocation. Signed-off-by: Stephen Warren Reviewed-by: Tom Rini Acked-by: Simon Glass # v1 Tested-by: Simon Glass # v1 Acked-by: Simon Glass --- tools/buildman/README | 42 +++++++++++++++++++++++++++++++++ tools/buildman/builder.py | 10 ++++++-- tools/buildman/builderthread.py | 24 ++++++++++++------- tools/buildman/cmdline.py | 4 ++++ tools/buildman/control.py | 4 +++- 5 files changed, 73 insertions(+), 11 deletions(-) diff --git a/tools/buildman/README b/tools/buildman/README index 4705d2644b..26755c5955 100644 --- a/tools/buildman/README +++ b/tools/buildman/README @@ -898,6 +898,48 @@ when using the -b flag. For example: will build commits in us-buildman that are not in upstream/master. +Building Faster +=============== + +By default, buildman executes 'make mrproper' prior to building the first +commit for each board. This causes everything to be built from scratch. If you +trust the build system's incremental build capabilities, you can pass the -I +flag to skip the 'make mproper' invocation, which will reduce the amount of +work 'make' does, and hence speed up the build. This flag will speed up any +buildman invocation, since it reduces the amount of work done on any build. + +One possible application of buildman is as part of a continual edit, build, +edit, build, ... cycle; repeatedly applying buildman to the same change or +series of changes while making small incremental modifications to the source +each time. This provides quick feedback regarding the correctness of recent +modifications. In this scenario, buildman's default choice of build directory +causes more build work to be performed than strictly necessary. + +By default, each buildman thread uses a single directory for all builds. When a +thread builds multiple boards, the configuration built in this directory will +cycle through various different configurations, one per board built by the +thread. Variations in the configuration will force a rebuild of affected source +files when a thread switches between boards. Ideally, such buildman-induced +rebuilds would not happen, thus allowing the build to operate as efficiently as +the build system and source changes allow. buildman's -P flag may be used to +enable this; -P causes each board to be built in a separate (board-specific) +directory, thus avoiding any buildman-induced configuration changes in any +build directory. + +U-Boot's build system embeds information such as a build timestamp into the +final binary. This information varies each time U-Boot is built. This causes +various files to be rebuilt even if no source changes are made, which in turn +requires that the final U-Boot binary be re-linked. This unnecessary work can +be avoided by turning off the timestamp feature. This can be achieved by +setting the SOURCE_DATE_EPOCH environment variable to 0. + +Combining all of these options together yields the command-line shown below. +This will provide the quickest possible feedback regarding the current content +of the source tree, thus allowing rapid tested evolution of the code. + + SOURCE_DATE_EPOCH=0 ./tools/buildman/buildman -I -P tegra + + Other options ============= diff --git a/tools/buildman/builder.py b/tools/buildman/builder.py index 141bf64691..8ec3551729 100644 --- a/tools/buildman/builder.py +++ b/tools/buildman/builder.py @@ -205,7 +205,8 @@ class Builder: def __init__(self, toolchains, base_dir, git_dir, num_threads, num_jobs, gnu_make='make', checkout=True, show_unknown=True, step=1, - no_subdirs=False, full_path=False, verbose_build=False): + no_subdirs=False, full_path=False, verbose_build=False, + incremental=False, per_board_out_dir=False): """Create a new Builder object Args: @@ -224,6 +225,10 @@ class Builder: full_path: Return the full path in CROSS_COMPILE and don't set PATH verbose_build: Run build with V=1 and don't use 'make -s' + incremental: Always perform incremental builds; don't run make + mrproper when configuring + per_board_out_dir: Build in a separate persistent directory per + board rather than a thread-specific directory """ self.toolchains = toolchains self.base_dir = base_dir @@ -263,7 +268,8 @@ class Builder: self.queue = Queue.Queue() self.out_queue = Queue.Queue() for i in range(self.num_threads): - t = builderthread.BuilderThread(self, i) + t = builderthread.BuilderThread(self, i, incremental, + per_board_out_dir) t.setDaemon(True) t.start() self.threads.append(t) diff --git a/tools/buildman/builderthread.py b/tools/buildman/builderthread.py index cf25bb8f1a..c512d3b521 100644 --- a/tools/buildman/builderthread.py +++ b/tools/buildman/builderthread.py @@ -80,11 +80,13 @@ class BuilderThread(threading.Thread): thread_num: Our thread number (0-n-1), used to decide on a temporary directory """ - def __init__(self, builder, thread_num): + def __init__(self, builder, thread_num, incremental, per_board_out_dir): """Set up a new builder thread""" threading.Thread.__init__(self) self.builder = builder self.thread_num = thread_num + self.incremental = incremental + self.per_board_out_dir = per_board_out_dir def Make(self, commit, brd, stage, cwd, *args, **kwargs): """Run 'make' on a particular commit and board. @@ -136,7 +138,11 @@ class BuilderThread(threading.Thread): if self.builder.in_tree: out_dir = work_dir else: - out_dir = os.path.join(work_dir, 'build') + if self.per_board_out_dir: + out_rel_dir = os.path.join('..', brd.target) + else: + out_rel_dir = 'build' + out_dir = os.path.join(work_dir, out_rel_dir) # Check if the job was already completed last time done_file = self.builder.GetDoneFile(commit_upto, brd.target) @@ -197,12 +203,12 @@ class BuilderThread(threading.Thread): # # Symlinks can confuse U-Boot's Makefile since # we may use '..' in our path, so remove them. - work_dir = os.path.realpath(work_dir) - args.append('O=%s/build' % work_dir) + out_dir = os.path.realpath(out_dir) + args.append('O=%s' % out_dir) cwd = None src_dir = os.getcwd() else: - args.append('O=build') + args.append('O=%s' % out_rel_dir) if self.builder.verbose_build: args.append('V=1') else: @@ -215,9 +221,11 @@ class BuilderThread(threading.Thread): # If we need to reconfigure, do that now if do_config: - result = self.Make(commit, brd, 'mrproper', cwd, - 'mrproper', *args, env=env) - config_out = result.combined + config_out = '' + if not self.incremental: + result = self.Make(commit, brd, 'mrproper', cwd, + 'mrproper', *args, env=env) + config_out += result.combined result = self.Make(commit, brd, 'config', cwd, *(args + config_args), env=env) config_out += result.combined diff --git a/tools/buildman/cmdline.py b/tools/buildman/cmdline.py index 8341ab145c..3e3bd63e32 100644 --- a/tools/buildman/cmdline.py +++ b/tools/buildman/cmdline.py @@ -49,6 +49,8 @@ def ParseArgs(): parser.add_option('-i', '--in-tree', dest='in_tree', action='store_true', default=False, help='Build in the source tree instead of a separate directory') + parser.add_option('-I', '--incremental', action='store_true', + default=False, help='Do not run make mrproper (when reconfiguring)') parser.add_option('-j', '--jobs', dest='jobs', type='int', default=None, help='Number of jobs to run at once (passed to make)') parser.add_option('-k', '--keep-outputs', action='store_true', @@ -70,6 +72,8 @@ def ParseArgs(): default=False, help='Do a rough build, with limited warning resolution') parser.add_option('-p', '--full-path', action='store_true', default=False, help="Use full toolchain path in CROSS_COMPILE") + parser.add_option('-P', '--per-board-out-dir', action='store_true', + default=False, help="Use an O= (output) directory per board rather than per thread") parser.add_option('-s', '--summary', action='store_true', default=False, help='Show a build summary') parser.add_option('-S', '--show-sizes', action='store_true', diff --git a/tools/buildman/control.py b/tools/buildman/control.py index c2c54bf0e8..aeb128a6a3 100644 --- a/tools/buildman/control.py +++ b/tools/buildman/control.py @@ -250,7 +250,9 @@ def DoBuildman(options, args, toolchains=None, make_func=None, boards=None, options.threads, options.jobs, gnu_make=gnu_make, checkout=True, show_unknown=options.show_unknown, step=options.step, no_subdirs=options.no_subdirs, full_path=options.full_path, - verbose_build=options.verbose_build) + verbose_build=options.verbose_build, + incremental=options.incremental, + per_board_out_dir=options.per_board_out_dir,) builder.force_config_on_failure = not options.quick if make_func: builder.do_make = make_func From 9fdfadf8fc83b173b3ba55aa82739ca92d8a273d Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Tue, 19 Apr 2016 16:19:29 -0600 Subject: [PATCH 023/162] dm: core: allow drivers to refuse to bind In some cases, drivers may not want to bind to a device. Allow bind() to return -ENODEV in this case, and don't treat this as an error. This can be useful in situations where some information source other than the DT node's main status property indicates whether the device should be enabled, for example other DT properties might indicate this, or the driver might query non-DT sources such as system fuses or a version number register. Signed-off-by: Stephen Warren Reviewed-by: Simon Glass --- drivers/core/lists.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/core/lists.c b/drivers/core/lists.c index c4fc216340..a72db13a11 100644 --- a/drivers/core/lists.c +++ b/drivers/core/lists.c @@ -171,6 +171,10 @@ int lists_bind_fdt(struct udevice *parent, const void *blob, int offset, dm_dbg(" - found match at '%s'\n", entry->name); ret = device_bind(parent, entry, name, NULL, offset, &dev); + if (ret == -ENODEV) { + dm_dbg("Driver '%s' refuses to bind\n", entry->name); + continue; + } if (ret) { dm_warn("Error binding driver '%s': %d\n", entry->name, ret); From 54693cbdca5724b8946d0522a736e8a49fa14c0c Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Tue, 19 Apr 2016 16:19:30 -0600 Subject: [PATCH 024/162] video: tegra: refuse to bind to disabled dcs This prevents the following boot-time message on any board where only the first DC is in use, yet the DC's DT node is enabled: stdio_add_devices: Video device failed (ret=-22) (This happens on at least Harmony, Ventana, and likely any other Tegra20 board with display enabled other than Seaboard). The Tegra DC's DT node represents a display controller. It may itself drive an integrated RGB display output, or be used by some other display controller such as HDMI. For this reason the DC node itself is not enabled/disabled in DT; the DC itself is considered a shared resource, not the final (board-specific) display output. The node should instantiate a display output driver only if the rgb subnode is enabled. Other output drivers are free to use the DC if they are enabled and their DT node references the DC's DT node. Adapt the Tegra display drivers' bind() routine to only bind to the DC's DT node if the RGB subnode is enabled. Now that the display driver does the right thing, remove the workaround for this issue from Seaboard's DT file. Cc: Thierry Reding Signed-off-by: Stephen Warren Acked-by: Thierry Reding Reviewed-by: Simon Glass --- arch/arm/dts/tegra20-seaboard.dts | 4 ---- drivers/video/tegra.c | 7 +++++++ 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/arch/arm/dts/tegra20-seaboard.dts b/arch/arm/dts/tegra20-seaboard.dts index eada59073e..5893d2a3f8 100644 --- a/arch/arm/dts/tegra20-seaboard.dts +++ b/arch/arm/dts/tegra20-seaboard.dts @@ -40,10 +40,6 @@ nvidia,panel = <&lcd_panel>; }; }; - - dc@54240000 { - status = "disabled"; - }; }; /* This is not used in U-Boot, but is expected to be in kernel .dts */ diff --git a/drivers/video/tegra.c b/drivers/video/tegra.c index 7fd10e6af3..c01809e89e 100644 --- a/drivers/video/tegra.c +++ b/drivers/video/tegra.c @@ -620,6 +620,13 @@ static int tegra_lcd_ofdata_to_platdata(struct udevice *dev) static int tegra_lcd_bind(struct udevice *dev) { struct video_uc_platdata *plat = dev_get_uclass_platdata(dev); + const void *blob = gd->fdt_blob; + int node = dev->of_offset; + int rgb; + + rgb = fdt_subnode_offset(blob, node, "rgb"); + if ((rgb < 0) || !fdtdec_get_is_enabled(blob, rgb)) + return -ENODEV; plat->size = LCD_MAX_WIDTH * LCD_MAX_HEIGHT * (1 << LCD_MAX_LOG2_BPP) / 8; From 35732098db382b48e3fb4f3595fc108f69ea4457 Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Thu, 28 Apr 2016 16:04:15 -0600 Subject: [PATCH 025/162] fdt: fix dev_get_addr_name node offset Use the device's own DT offset, not the device's parent's. Fixes: 43c4d44e3330 ("fdt: implement dev_get_addr_name()") Signed-off-by: Stephen Warren Acked-by: Simon Glass --- drivers/core/device.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/core/device.c b/drivers/core/device.c index 1322991d6c..2b12ce7835 100644 --- a/drivers/core/device.c +++ b/drivers/core/device.c @@ -657,8 +657,8 @@ fdt_addr_t dev_get_addr_name(struct udevice *dev, const char *name) #if CONFIG_IS_ENABLED(OF_CONTROL) int index; - index = fdt_find_string(gd->fdt_blob, dev->parent->of_offset, - "reg-names", name); + index = fdt_find_string(gd->fdt_blob, dev->of_offset, "reg-names", + name); if (index < 0) return index; From b6d54d527325f27c460777b882e23d21a935765a Mon Sep 17 00:00:00 2001 From: Peng Fan Date: Tue, 3 May 2016 10:02:20 +0800 Subject: [PATCH 026/162] dm: spi: soft_spi bug fix When doing xfer, should use device->parent, but not device When doing bit xfer, should use "!!(tmpdout & 0x80)", but not "(tmpdout & 0x80)" Signed-off-by: Peng Fan Cc: Simon Glass Cc: Jagan Teki Reviewed-by: Simon Glass --- drivers/spi/soft_spi.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/drivers/spi/soft_spi.c b/drivers/spi/soft_spi.c index aa4abcc3d2..8cdb520608 100644 --- a/drivers/spi/soft_spi.c +++ b/drivers/spi/soft_spi.c @@ -34,7 +34,8 @@ struct soft_spi_priv { static int soft_spi_scl(struct udevice *dev, int bit) { - struct soft_spi_platdata *plat = dev->platdata; + struct udevice *bus = dev_get_parent(dev); + struct soft_spi_platdata *plat = dev_get_platdata(bus); dm_gpio_set_value(&plat->sclk, bit); @@ -43,7 +44,8 @@ static int soft_spi_scl(struct udevice *dev, int bit) static int soft_spi_sda(struct udevice *dev, int bit) { - struct soft_spi_platdata *plat = dev->platdata; + struct udevice *bus = dev_get_parent(dev); + struct soft_spi_platdata *plat = dev_get_platdata(bus); dm_gpio_set_value(&plat->mosi, bit); @@ -52,7 +54,8 @@ static int soft_spi_sda(struct udevice *dev, int bit) static int soft_spi_cs_activate(struct udevice *dev) { - struct soft_spi_platdata *plat = dev->platdata; + struct udevice *bus = dev_get_parent(dev); + struct soft_spi_platdata *plat = dev_get_platdata(bus); dm_gpio_set_value(&plat->cs, 0); dm_gpio_set_value(&plat->sclk, 0); @@ -63,7 +66,8 @@ static int soft_spi_cs_activate(struct udevice *dev) static int soft_spi_cs_deactivate(struct udevice *dev) { - struct soft_spi_platdata *plat = dev->platdata; + struct udevice *bus = dev_get_parent(dev); + struct soft_spi_platdata *plat = dev_get_platdata(bus); dm_gpio_set_value(&plat->cs, 0); @@ -100,8 +104,9 @@ static int soft_spi_release_bus(struct udevice *dev) static int soft_spi_xfer(struct udevice *dev, unsigned int bitlen, const void *dout, void *din, unsigned long flags) { - struct soft_spi_priv *priv = dev_get_priv(dev); - struct soft_spi_platdata *plat = dev->platdata; + struct udevice *bus = dev_get_parent(dev); + struct soft_spi_priv *priv = dev_get_priv(bus); + struct soft_spi_platdata *plat = dev_get_platdata(bus); uchar tmpdin = 0; uchar tmpdout = 0; const u8 *txd = dout; @@ -134,7 +139,7 @@ static int soft_spi_xfer(struct udevice *dev, unsigned int bitlen, if (!cpha) soft_spi_scl(dev, 0); - soft_spi_sda(dev, tmpdout & 0x80); + soft_spi_sda(dev, !!(tmpdout & 0x80)); udelay(plat->spi_delay_us); if (cpha) soft_spi_scl(dev, 0); From 102412c415b5e51b01ed5797c965d0feaa065439 Mon Sep 17 00:00:00 2001 From: Peng Fan Date: Tue, 3 May 2016 10:02:21 +0800 Subject: [PATCH 027/162] dm: spi: soft_spi: switch to use linux compatible string 1. Support compatible string "spi-gpio" which is used by Linux Linux use different bindings, so use UBOOT_COMPAT and LINUX_COMPAT to differentiate them. 2. Introduce SPI_MASTER_NO_RX and SPI_MASTER_NO_TX to handle no rx or no tx case. 3. Tested on i.MX6 UltraLite board with 74LV595 spi-gpio chip. Signed-off-by: Peng Fan Cc: Simon Glass Cc: Przemyslaw Marczak Reviewed-by: Simon Glass --- arch/arm/dts/exynos4210-universal_c210.dts | 10 +++--- drivers/spi/soft_spi.c | 38 ++++++++++++++++------ 2 files changed, 33 insertions(+), 15 deletions(-) diff --git a/arch/arm/dts/exynos4210-universal_c210.dts b/arch/arm/dts/exynos4210-universal_c210.dts index 16948c9342..ad3527ec6f 100644 --- a/arch/arm/dts/exynos4210-universal_c210.dts +++ b/arch/arm/dts/exynos4210-universal_c210.dts @@ -42,11 +42,11 @@ }; soft-spi { - compatible = "u-boot,soft-spi"; - cs-gpio = <&gpy4 3 0>; - sclk-gpio = <&gpy3 1 0>; - mosi-gpio = <&gpy3 3 0>; - miso-gpio = <&gpy3 0 0>; + compatible = "spi-gpio"; + cs-gpios = <&gpy4 3 0>; + gpio-sck = <&gpy3 1 0>; + gpio-mosi = <&gpy3 3 0>; + gpio-miso = <&gpy3 0 0>; spi-delay-us = <1>; #address-cells = <1>; #size-cells = <0>; diff --git a/drivers/spi/soft_spi.c b/drivers/spi/soft_spi.c index 8cdb520608..d23dc81a21 100644 --- a/drivers/spi/soft_spi.c +++ b/drivers/spi/soft_spi.c @@ -26,8 +26,12 @@ struct soft_spi_platdata { struct gpio_desc mosi; struct gpio_desc miso; int spi_delay_us; + int flags; }; +#define SPI_MASTER_NO_RX BIT(0) +#define SPI_MASTER_NO_TX BIT(1) + struct soft_spi_priv { unsigned int mode; }; @@ -139,14 +143,16 @@ static int soft_spi_xfer(struct udevice *dev, unsigned int bitlen, if (!cpha) soft_spi_scl(dev, 0); - soft_spi_sda(dev, !!(tmpdout & 0x80)); + if ((plat->flags & SPI_MASTER_NO_TX) == 0) + soft_spi_sda(dev, !!(tmpdout & 0x80)); udelay(plat->spi_delay_us); if (cpha) soft_spi_scl(dev, 0); else soft_spi_scl(dev, 1); tmpdin <<= 1; - tmpdin |= dm_gpio_get_value(&plat->miso); + if ((plat->flags & SPI_MASTER_NO_RX) == 0) + tmpdin |= dm_gpio_get_value(&plat->miso); tmpdout <<= 1; udelay(plat->spi_delay_us); if (cpha) @@ -208,24 +214,36 @@ static int soft_spi_probe(struct udevice *dev) struct spi_slave *slave = dev_get_parent_priv(dev); struct soft_spi_platdata *plat = dev->platdata; int cs_flags, clk_flags; + int ret; cs_flags = (slave->mode & SPI_CS_HIGH) ? 0 : GPIOD_ACTIVE_LOW; clk_flags = (slave->mode & SPI_CPOL) ? GPIOD_ACTIVE_LOW : 0; - if (gpio_request_by_name(dev, "cs-gpio", 0, &plat->cs, + + if (gpio_request_by_name(dev, "cs-gpios", 0, &plat->cs, GPIOD_IS_OUT | cs_flags) || - gpio_request_by_name(dev, "sclk-gpio", 0, &plat->sclk, - GPIOD_IS_OUT | clk_flags) || - gpio_request_by_name(dev, "mosi-gpio", 0, &plat->mosi, - GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE) || - gpio_request_by_name(dev, "miso-gpio", 0, &plat->miso, - GPIOD_IS_IN)) + gpio_request_by_name(dev, "gpio-sck", 0, &plat->sclk, + GPIOD_IS_OUT | clk_flags)) + return -EINVAL; + + ret = gpio_request_by_name(dev, "gpio-mosi", 0, &plat->mosi, + GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE); + if (ret) + plat->flags |= SPI_MASTER_NO_TX; + + ret = gpio_request_by_name(dev, "gpio-miso", 0, &plat->miso, + GPIOD_IS_IN); + if (ret) + plat->flags |= SPI_MASTER_NO_RX; + + if ((plat->flags & (SPI_MASTER_NO_RX | SPI_MASTER_NO_TX)) == + (SPI_MASTER_NO_RX | SPI_MASTER_NO_TX)) return -EINVAL; return 0; } static const struct udevice_id soft_spi_ids[] = { - { .compatible = "u-boot,soft-spi" }, + { .compatible = "spi-gpio" }, { } }; From 7a3eff4ce962de50bd9a1d83a9fce178c04999d3 Mon Sep 17 00:00:00 2001 From: Peng Fan Date: Tue, 3 May 2016 10:02:22 +0800 Subject: [PATCH 028/162] dm: spi: introduce dm api Introduce dm_spi_claim_bus, dm_spi_release_bus and dm_spi_xfer Convert spi_claim_bus, spi_release_bus and spi_xfer to use the new API. Signed-off-by: Peng Fan Cc: Simon Glass Cc: Jagan Teki Acked-by: Simon Glass --- drivers/spi/spi-uclass.c | 28 ++++++++++++++++------ include/spi.h | 52 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 73 insertions(+), 7 deletions(-) diff --git a/drivers/spi/spi-uclass.c b/drivers/spi/spi-uclass.c index 5561f36762..84b6786517 100644 --- a/drivers/spi/spi-uclass.c +++ b/drivers/spi/spi-uclass.c @@ -45,12 +45,12 @@ static int spi_set_speed_mode(struct udevice *bus, int speed, int mode) return 0; } -int spi_claim_bus(struct spi_slave *slave) +int dm_spi_claim_bus(struct udevice *dev) { - struct udevice *dev = slave->dev; struct udevice *bus = dev->parent; struct dm_spi_ops *ops = spi_get_ops(bus); struct dm_spi_bus *spi = dev_get_uclass_priv(bus); + struct spi_slave *slave = dev_get_parent_priv(dev); int speed; int ret; @@ -73,9 +73,8 @@ int spi_claim_bus(struct spi_slave *slave) return ops->claim_bus ? ops->claim_bus(dev) : 0; } -void spi_release_bus(struct spi_slave *slave) +void dm_spi_release_bus(struct udevice *dev) { - struct udevice *dev = slave->dev; struct udevice *bus = dev->parent; struct dm_spi_ops *ops = spi_get_ops(bus); @@ -83,10 +82,9 @@ void spi_release_bus(struct spi_slave *slave) ops->release_bus(dev); } -int spi_xfer(struct spi_slave *slave, unsigned int bitlen, - const void *dout, void *din, unsigned long flags) +int dm_spi_xfer(struct udevice *dev, unsigned int bitlen, + const void *dout, void *din, unsigned long flags) { - struct udevice *dev = slave->dev; struct udevice *bus = dev->parent; if (bus->uclass->uc_drv->id != UCLASS_SPI) @@ -95,6 +93,22 @@ int spi_xfer(struct spi_slave *slave, unsigned int bitlen, return spi_get_ops(bus)->xfer(dev, bitlen, dout, din, flags); } +int spi_claim_bus(struct spi_slave *slave) +{ + return dm_spi_claim_bus(slave->dev); +} + +void spi_release_bus(struct spi_slave *slave) +{ + dm_spi_release_bus(slave->dev); +} + +int spi_xfer(struct spi_slave *slave, unsigned int bitlen, + const void *dout, void *din, unsigned long flags) +{ + return dm_spi_xfer(slave->dev, bitlen, dout, din, flags); +} + static int spi_post_bind(struct udevice *dev) { /* Scan the bus for devices */ diff --git a/include/spi.h b/include/spi.h index 4b88d3986e..ca96fa4b31 100644 --- a/include/spi.h +++ b/include/spi.h @@ -612,6 +612,58 @@ int sandbox_spi_get_emul(struct sandbox_state *state, struct udevice *bus, struct udevice *slave, struct udevice **emulp); +/** + * Claim the bus and prepare it for communication with a given slave. + * + * This must be called before doing any transfers with a SPI slave. It + * will enable and initialize any SPI hardware as necessary, and make + * sure that the SCK line is in the correct idle state. It is not + * allowed to claim the same bus for several slaves without releasing + * the bus in between. + * + * @dev: The SPI slave device + * + * Returns: 0 if the bus was claimed successfully, or a negative value + * if it wasn't. + */ +int dm_spi_claim_bus(struct udevice *dev); + +/** + * Release the SPI bus + * + * This must be called once for every call to dm_spi_claim_bus() after + * all transfers have finished. It may disable any SPI hardware as + * appropriate. + * + * @slave: The SPI slave device + */ +void dm_spi_release_bus(struct udevice *dev); + +/** + * SPI transfer + * + * This writes "bitlen" bits out the SPI MOSI port and simultaneously clocks + * "bitlen" bits in the SPI MISO port. That's just the way SPI works. + * + * The source of the outgoing bits is the "dout" parameter and the + * destination of the input bits is the "din" parameter. Note that "dout" + * and "din" can point to the same memory location, in which case the + * input data overwrites the output data (since both are buffered by + * temporary variables, this is OK). + * + * dm_spi_xfer() interface: + * @dev: The SPI slave device which will be sending/receiving the data. + * @bitlen: How many bits to write and read. + * @dout: Pointer to a string of bits to send out. The bits are + * held in a byte array and are sent MSB first. + * @din: Pointer to a string of bits that will be filled in. + * @flags: A bitwise combination of SPI_XFER_* flags. + * + * Returns: 0 on success, not 0 on failure + */ +int dm_spi_xfer(struct udevice *dev, unsigned int bitlen, + const void *dout, void *din, unsigned long flags); + /* Access the operations for a SPI device */ #define spi_get_ops(dev) ((struct dm_spi_ops *)(dev)->driver->ops) #define spi_emul_get_ops(dev) ((struct dm_spi_emul_ops *)(dev)->driver->ops) From 9300f711baac8a181f70d7f64978e4bbadd4ac5c Mon Sep 17 00:00:00 2001 From: Peng Fan Date: Tue, 3 May 2016 10:02:23 +0800 Subject: [PATCH 029/162] dm: gpio: introduce 74x164 driver Introduce driver to support "fairchild,74hc595" devices. 1. Take linux drivers/drivers/gpio/gpio-74x164.c as reference. 2. Following the naming used in Linux driver with gen_7x164 as the prefix. 3. Enable CONFIG_DM_74X164 to use this driver. 4. Follow Documentation/devicetree/bindings/gpio/gpio-74x164.txt to add device nodes 5. Tested on i.MX6 UltraLite with 74LV595 using gpio command and oscillograph. Signed-off-by: Peng Fan Cc: Simon Glass Cc: Masahiro Yamada Cc: Chin Liang See Cc: Bhuvanchandra DV Cc: Daniel Schwierzeck Cc: Fabio Estevam Cc: Stefano Babic Reviewed-by: Simon Glass --- drivers/gpio/74x164_gpio.c | 193 +++++++++++++++++++++++++++++++++++++ drivers/gpio/Kconfig | 8 ++ drivers/gpio/Makefile | 1 + 3 files changed, 202 insertions(+) create mode 100644 drivers/gpio/74x164_gpio.c diff --git a/drivers/gpio/74x164_gpio.c b/drivers/gpio/74x164_gpio.c new file mode 100644 index 0000000000..9ac10a745d --- /dev/null +++ b/drivers/gpio/74x164_gpio.c @@ -0,0 +1,193 @@ +/* + * Take drivers/gpio/gpio-74x164.c as reference. + * + * 74Hx164 - Generic serial-in/parallel-out 8-bits shift register GPIO driver + * + * Copyright (C) 2016 Peng Fan + * + * SPDX-License-Identifier: GPL-2.0+ + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +DECLARE_GLOBAL_DATA_PTR; + +/* + * struct gen_74x164_chip - Data for 74Hx164 + * + * @oe: OE pin + * @nregs: number of registers + * @buffer: buffer for chained chips + */ +#define GEN_74X164_NUMBER_GPIOS 8 + +struct gen_74x164_priv { + struct gpio_desc oe; + u32 nregs; + /* + * Since the nregs are chained, every byte sent will make + * the previous byte shift to the next register in the + * chain. Thus, the first byte sent will end up in the last + * register at the end of the transfer. So, to have a logical + * numbering, store the bytes in reverse order. + */ + u8 *buffer; +}; + +static int gen_74x164_write_conf(struct udevice *dev) +{ + struct gen_74x164_priv *priv = dev_get_priv(dev); + int ret; + + ret = dm_spi_claim_bus(dev); + if (ret) + return ret; + + ret = dm_spi_xfer(dev, priv->nregs * 8, priv->buffer, NULL, + SPI_XFER_BEGIN | SPI_XFER_END); + + dm_spi_release_bus(dev); + + return ret; +} + +static int gen_74x164_get_value(struct udevice *dev, unsigned offset) +{ + struct gen_74x164_priv *priv = dev_get_priv(dev); + uint bank = priv->nregs - 1 - offset / 8; + uint pin = offset % 8; + + return (priv->buffer[bank] >> pin) & 0x1; +} + +static int gen_74x164_set_value(struct udevice *dev, unsigned offset, + int value) +{ + struct gen_74x164_priv *priv = dev_get_priv(dev); + uint bank = priv->nregs - 1 - offset / 8; + uint pin = offset % 8; + int ret; + + if (value) + priv->buffer[bank] |= 1 << pin; + else + priv->buffer[bank] &= ~(1 << pin); + + ret = gen_74x164_write_conf(dev); + if (ret) + return ret; + + return 0; +} + +static int gen_74x164_direction_input(struct udevice *dev, unsigned offset) +{ + return -ENOSYS; +} + +static int gen_74x164_direction_output(struct udevice *dev, unsigned offset, + int value) +{ + return gen_74x164_set_value(dev, offset, value); +} + +static int gen_74x164_get_function(struct udevice *dev, unsigned offset) +{ + return GPIOF_OUTPUT; +} + +static int gen_74x164_xlate(struct udevice *dev, struct gpio_desc *desc, + struct fdtdec_phandle_args *args) +{ + desc->offset = args->args[0]; + desc->flags = args->args[1] & GPIO_ACTIVE_LOW ? GPIOD_ACTIVE_LOW : 0; + + return 0; +} + +static const struct dm_gpio_ops gen_74x164_ops = { + .direction_input = gen_74x164_direction_input, + .direction_output = gen_74x164_direction_output, + .get_value = gen_74x164_get_value, + .set_value = gen_74x164_set_value, + .get_function = gen_74x164_get_function, + .xlate = gen_74x164_xlate, +}; + +static int gen_74x164_probe(struct udevice *dev) +{ + struct gen_74x164_priv *priv = dev_get_priv(dev); + struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev); + char *str, name[32]; + int ret; + const void *fdt = gd->fdt_blob; + int node = dev->of_offset; + + snprintf(name, sizeof(name), "%s_", dev->name); + str = strdup(name); + if (!str) + return -ENOMEM; + + /* + * See Linux kernel: + * Documentation/devicetree/bindings/gpio/gpio-74x164.txt + */ + priv->nregs = fdtdec_get_int(fdt, node, "registers-number", 1); + priv->buffer = calloc(priv->nregs, sizeof(u8)); + if (!priv->buffer) { + ret = -ENOMEM; + goto free_str; + } + + ret = fdtdec_get_byte_array(fdt, node, "registers-default", + priv->buffer, priv->nregs); + if (ret) + dev_dbg(dev, "No registers-default property\n"); + + ret = gpio_request_by_name(dev, "oe-gpios", 0, &priv->oe, + GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE); + if (ret) { + dev_err(dev, "No oe-pins property\n"); + goto free_buf; + } + + uc_priv->bank_name = str; + uc_priv->gpio_count = priv->nregs * 8; + + ret = gen_74x164_write_conf(dev); + if (ret) + goto free_buf; + + dev_dbg(dev, "%s is ready\n", dev->name); + + return 0; + +free_buf: + free(priv->buffer); +free_str: + free(str); + return ret; +} + +static const struct udevice_id gen_74x164_ids[] = { + { .compatible = "fairchild,74hc595" }, + { } +}; + +U_BOOT_DRIVER(74x164) = { + .name = "74x164", + .id = UCLASS_GPIO, + .ops = &gen_74x164_ops, + .probe = gen_74x164_probe, + .priv_auto_alloc_size = sizeof(struct gen_74x164_priv), + .of_match = gen_74x164_ids, +}; diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index e6337c24d8..93a7e8c6c2 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -143,6 +143,14 @@ config ZYNQ_GPIO help Supports GPIO access on Zynq SoC. +config DM_74X164 + bool "74x164 serial-in/parallel-out 8-bits shift register" + depends on DM_GPIO + help + Driver for 74x164 compatible serial-in/parallel-out 8-outputs + shift registers, such as 74lv165, 74hc595. + This driver can be used to provide access to more gpio outputs. + config DM_PCA953X bool "PCA95[357]x, PCA9698, TCA64xx, and MAX7310 I/O ports" depends on DM_GPIO diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index 4b1f6b9301..ddec1ef8de 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -12,6 +12,7 @@ endif obj-$(CONFIG_DM_GPIO) += gpio-uclass.o obj-$(CONFIG_DM_PCA953X) += pca953x_gpio.o +obj-$(CONFIG_DM_74X164) += 74x164_gpio.o obj-$(CONFIG_AT91_GPIO) += at91_gpio.o obj-$(CONFIG_ATMEL_PIO4) += atmel_pio4.o From c0c62d923344d5a68f43259282e68a827318db01 Mon Sep 17 00:00:00 2001 From: Mugunthan V N Date: Tue, 12 Apr 2016 16:01:19 +0530 Subject: [PATCH 030/162] drivers: usb: common: add common code for usb drivers to use Add common usb code which usb drivers makes use of it. Signed-off-by: Mugunthan V N Reviewed-by: Simon Glass --- drivers/usb/common/Makefile | 1 + drivers/usb/common/common.c | 40 +++++++++++++++++++++++++++++++++++++ include/linux/usb/otg.h | 9 +++++++++ 3 files changed, 50 insertions(+) create mode 100644 drivers/usb/common/common.c diff --git a/drivers/usb/common/Makefile b/drivers/usb/common/Makefile index 2f3d43d939..2f46d38d2b 100644 --- a/drivers/usb/common/Makefile +++ b/drivers/usb/common/Makefile @@ -3,5 +3,6 @@ # SPDX-License-Identifier: GPL-2.0+ # +obj-$(CONFIG_DM_USB) += common.o obj-$(CONFIG_USB_EHCI_FSL) += fsl-dt-fixup.o obj-$(CONFIG_USB_XHCI_FSL) += fsl-dt-fixup.o diff --git a/drivers/usb/common/common.c b/drivers/usb/common/common.c new file mode 100644 index 0000000000..35c2dc18d9 --- /dev/null +++ b/drivers/usb/common/common.c @@ -0,0 +1,40 @@ +/* + * Provides code common for host and device side USB. + * + * (C) Copyright 2016 + * Texas Instruments Incorporated, + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include + +DECLARE_GLOBAL_DATA_PTR; + +static const char *const usb_dr_modes[] = { + [USB_DR_MODE_UNKNOWN] = "", + [USB_DR_MODE_HOST] = "host", + [USB_DR_MODE_PERIPHERAL] = "peripheral", + [USB_DR_MODE_OTG] = "otg", +}; + +enum usb_dr_mode usb_get_dr_mode(int node) +{ + const void *fdt = gd->fdt_blob; + const char *dr_mode; + int i; + + dr_mode = fdt_getprop(fdt, node, "dr_mode", NULL); + if (!dr_mode) { + error("usb dr_mode not found\n"); + return USB_DR_MODE_UNKNOWN; + } + + for (i = 0; i < ARRAY_SIZE(usb_dr_modes); i++) + if (!strcmp(dr_mode, usb_dr_modes[i])) + return i; + + return USB_DR_MODE_UNKNOWN; +} diff --git a/include/linux/usb/otg.h b/include/linux/usb/otg.h index 7ec5550f4b..8f8ac6aeef 100644 --- a/include/linux/usb/otg.h +++ b/include/linux/usb/otg.h @@ -17,4 +17,13 @@ enum usb_dr_mode { USB_DR_MODE_OTG, }; +/** + * usb_get_dr_mode() - Get dual role mode for given device + * @node: Node offset to the given device + * + * The function gets phy interface string from property 'dr_mode', + * and returns the correspondig enum usb_dr_mode + */ +enum usb_dr_mode usb_get_dr_mode(int node); + #endif /* __LINUX_USB_OTG_H */ From 6c880b7719d73dc4bf4bf828b6341e086e6f5eb6 Mon Sep 17 00:00:00 2001 From: Eric Nelson Date: Sun, 24 Apr 2016 16:32:40 -0700 Subject: [PATCH 031/162] dm: gpio: add a default gpio xlate routine Many drivers use a common form of offset + flags for device tree nodes. e.g.: <&gpio1 2 GPIO_ACTIVE_LOW> This patch adds a common implementation of this type of parsing and calls it when a gpio driver doesn't supply its' own xlate routine. This will allow removal of the driver-specific versions in a handful of drivers and simplify the addition of new drivers. Signed-off-by: Eric Nelson Reviewed-by: Stephen Warren Acked-by: Simon Glass --- drivers/gpio/gpio-uclass.c | 30 +++++++++++++++++++++++------- include/asm-generic/gpio.h | 19 ++++++++++++++----- 2 files changed, 37 insertions(+), 12 deletions(-) diff --git a/drivers/gpio/gpio-uclass.c b/drivers/gpio/gpio-uclass.c index b58d4e64e8..732b6c2afa 100644 --- a/drivers/gpio/gpio-uclass.c +++ b/drivers/gpio/gpio-uclass.c @@ -6,6 +6,7 @@ #include #include +#include #include #include #include @@ -113,19 +114,33 @@ int gpio_lookup_name(const char *name, struct udevice **devp, return 0; } +int gpio_xlate_offs_flags(struct udevice *dev, + struct gpio_desc *desc, + struct fdtdec_phandle_args *args) +{ + if (args->args_count < 1) + return -EINVAL; + + desc->offset = args->args[0]; + + if (args->args_count < 2) + return 0; + + if (args->args[1] & GPIO_ACTIVE_LOW) + desc->flags = GPIOD_ACTIVE_LOW; + + return 0; +} + static int gpio_find_and_xlate(struct gpio_desc *desc, struct fdtdec_phandle_args *args) { struct dm_gpio_ops *ops = gpio_get_ops(desc->dev); - /* Use the first argument as the offset by default */ - if (args->args_count > 0) - desc->offset = args->args[0]; + if (ops->xlate) + return ops->xlate(desc->dev, desc, args); else - desc->offset = -1; - desc->flags = 0; - - return ops->xlate ? ops->xlate(desc->dev, desc, args) : 0; + return gpio_xlate_offs_flags(desc->dev, desc, args); } int dm_gpio_request(struct gpio_desc *desc, const char *label) @@ -605,6 +620,7 @@ static int _gpio_request_by_name_nodev(const void *blob, int node, desc->dev = NULL; desc->offset = 0; + desc->flags = 0; ret = fdtdec_parse_phandle_with_args(blob, node, list_name, "#gpio-cells", 0, index, &args); if (ret) { diff --git a/include/asm-generic/gpio.h b/include/asm-generic/gpio.h index 68b5f0b3c2..2500c10450 100644 --- a/include/asm-generic/gpio.h +++ b/include/asm-generic/gpio.h @@ -206,6 +206,16 @@ int gpio_requestf(unsigned gpio, const char *fmt, ...) struct fdtdec_phandle_args; +/** + * gpio_xlate_offs_flags() - implementation for common use of dm_gpio_ops.xlate + * + * This routine sets the offset field to args[0] and the flags field to + * GPIOD_ACTIVE_LOW if the GPIO_ACTIVE_LOW flag is present in args[1]. + * + */ +int gpio_xlate_offs_flags(struct udevice *dev, struct gpio_desc *desc, + struct fdtdec_phandle_args *args); + /** * struct struct dm_gpio_ops - Driver model GPIO operations * @@ -258,12 +268,11 @@ struct dm_gpio_ops { * * @desc->dev to @dev * @desc->flags to 0 - * @desc->offset to the value of the first argument in args, if any, - * otherwise -1 (which is invalid) + * @desc->offset to 0 * - * This method is optional so if the above defaults suit it can be - * omitted. Typical behaviour is to set up the GPIOD_ACTIVE_LOW flag - * in desc->flags. + * This method is optional and defaults to gpio_xlate_offs_flags, + * which will parse offset and the GPIO_ACTIVE_LOW flag in the first + * two arguments. * * Note that @dev is passed in as a parameter to follow driver model * uclass conventions, even though it is already available as From 8376aaddaf29b5ec296759f2b374cf940b932962 Mon Sep 17 00:00:00 2001 From: Eric Nelson Date: Wed, 20 Apr 2016 08:37:35 -0700 Subject: [PATCH 032/162] gpio: intel_broadwell: remove gpio_xlate routine With the addition of GPIO_ACTIVE_LOW parsing in gpio-uclass, the intel_broadwell driver doesn't need a custom xlate routine. Signed-off-by: Eric Nelson Acked-by: Simon Glass --- drivers/gpio/intel_broadwell_gpio.c | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/drivers/gpio/intel_broadwell_gpio.c b/drivers/gpio/intel_broadwell_gpio.c index 8cf76f96c2..81ce446e1a 100644 --- a/drivers/gpio/intel_broadwell_gpio.c +++ b/drivers/gpio/intel_broadwell_gpio.c @@ -162,15 +162,6 @@ static int broadwell_gpio_ofdata_to_platdata(struct udevice *dev) return 0; } -static int broadwell_gpio_xlate(struct udevice *dev, struct gpio_desc *desc, - struct fdtdec_phandle_args *args) -{ - desc->offset = args->args[0]; - desc->flags = args->args[1] & GPIO_ACTIVE_LOW ? GPIOD_ACTIVE_LOW : 0; - - return 0; -} - static const struct dm_gpio_ops gpio_broadwell_ops = { .request = broadwell_gpio_request, .direction_input = broadwell_gpio_direction_input, @@ -178,7 +169,6 @@ static const struct dm_gpio_ops gpio_broadwell_ops = { .get_value = broadwell_gpio_get_value, .set_value = broadwell_gpio_set_value, .get_function = broadwell_gpio_get_function, - .xlate = broadwell_gpio_xlate, }; static const struct udevice_id intel_broadwell_gpio_ids[] = { From 86222f6140895e451eafefc25437a33fa394dba5 Mon Sep 17 00:00:00 2001 From: Eric Nelson Date: Wed, 20 Apr 2016 08:37:36 -0700 Subject: [PATCH 033/162] gpio: omap: remove gpio_xlate routine With the addition of GPIO_ACTIVE_LOW parsing in gpio-uclass, the omap gpio driver doesn't need a custom xlate routine. Signed-off-by: Eric Nelson Acked-by: Simon Glass --- drivers/gpio/omap_gpio.c | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/drivers/gpio/omap_gpio.c b/drivers/gpio/omap_gpio.c index 93d18e44a5..cd960dc013 100644 --- a/drivers/gpio/omap_gpio.c +++ b/drivers/gpio/omap_gpio.c @@ -25,7 +25,6 @@ #include #include #include -#include DECLARE_GLOBAL_DATA_PTR; @@ -277,22 +276,12 @@ static int omap_gpio_get_function(struct udevice *dev, unsigned offset) return GPIOF_INPUT; } -static int omap_gpio_xlate(struct udevice *dev, struct gpio_desc *desc, - struct fdtdec_phandle_args *args) -{ - desc->offset = args->args[0]; - desc->flags = args->args[1] & GPIO_ACTIVE_LOW ? GPIOD_ACTIVE_LOW : 0; - - return 0; -} - static const struct dm_gpio_ops gpio_omap_ops = { .direction_input = omap_gpio_direction_input, .direction_output = omap_gpio_direction_output, .get_value = omap_gpio_get_value, .set_value = omap_gpio_set_value, .get_function = omap_gpio_get_function, - .xlate = omap_gpio_xlate, }; static int omap_gpio_probe(struct udevice *dev) From 5206e7bff575e3c0b96b8db89c80d4f020ed7539 Mon Sep 17 00:00:00 2001 From: Eric Nelson Date: Wed, 20 Apr 2016 08:37:37 -0700 Subject: [PATCH 034/162] gpio: pic32: remove gpio_xlate routine With the addition of GPIO_ACTIVE_LOW parsing in gpio-uclass, the pic32 gpio driver doesn't need a custom xlate routine. Signed-off-by: Eric Nelson Acked-by: Simon Glass Reviewed-by: Purna Chandra Mandal --- drivers/gpio/pic32_gpio.c | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/drivers/gpio/pic32_gpio.c b/drivers/gpio/pic32_gpio.c index 499b4fa5ad..7a037f3a77 100644 --- a/drivers/gpio/pic32_gpio.c +++ b/drivers/gpio/pic32_gpio.c @@ -12,7 +12,6 @@ #include #include #include -#include #include DECLARE_GLOBAL_DATA_PTR; @@ -99,14 +98,6 @@ static int pic32_gpio_direction_output(struct udevice *dev, return 0; } -static int pic32_gpio_xlate(struct udevice *dev, struct gpio_desc *desc, - struct fdtdec_phandle_args *args) -{ - desc->flags = args->args[1] & GPIO_ACTIVE_LOW ? GPIOD_ACTIVE_LOW : 0; - - return 0; -} - static int pic32_gpio_get_function(struct udevice *dev, unsigned offset) { int ret = GPIOF_UNUSED; @@ -131,7 +122,6 @@ static const struct dm_gpio_ops gpio_pic32_ops = { .get_value = pic32_gpio_get_value, .set_value = pic32_gpio_set_value, .get_function = pic32_gpio_get_function, - .xlate = pic32_gpio_xlate, }; static int pic32_gpio_probe(struct udevice *dev) From 6c3dd3caf0e6469fa65819aec300210f97ad7536 Mon Sep 17 00:00:00 2001 From: Eric Nelson Date: Wed, 20 Apr 2016 08:37:38 -0700 Subject: [PATCH 035/162] gpio: rk: remove gpio_xlate routine With the addition of GPIO_ACTIVE_LOW parsing in gpio-uclass, the Rockchip gpio driver doesn't need a custom xlate routine. Signed-off-by: Eric Nelson Acked-by: Simon Glass --- drivers/gpio/rk_gpio.c | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/drivers/gpio/rk_gpio.c b/drivers/gpio/rk_gpio.c index 40e87bd199..fefe3ca203 100644 --- a/drivers/gpio/rk_gpio.c +++ b/drivers/gpio/rk_gpio.c @@ -16,7 +16,6 @@ #include #include #include -#include #include enum { @@ -98,15 +97,6 @@ static int rockchip_gpio_get_function(struct udevice *dev, unsigned offset) #endif } -static int rockchip_gpio_xlate(struct udevice *dev, struct gpio_desc *desc, - struct fdtdec_phandle_args *args) -{ - desc->offset = args->args[0]; - desc->flags = args->args[1] & GPIO_ACTIVE_LOW ? GPIOD_ACTIVE_LOW : 0; - - return 0; -} - static int rockchip_gpio_probe(struct udevice *dev) { struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev); @@ -135,7 +125,6 @@ static const struct dm_gpio_ops gpio_rockchip_ops = { .get_value = rockchip_gpio_get_value, .set_value = rockchip_gpio_set_value, .get_function = rockchip_gpio_get_function, - .xlate = rockchip_gpio_xlate, }; static const struct udevice_id rockchip_gpio_ids[] = { From f8353033884a25bedfef20e1fcc509db38a15218 Mon Sep 17 00:00:00 2001 From: Eric Nelson Date: Wed, 20 Apr 2016 08:37:39 -0700 Subject: [PATCH 036/162] gpio: exynos(s5p): remove gpio_xlate routine With the addition of GPIO_ACTIVE_LOW parsing in gpio-uclass, the Exynos/S5P gpio driver doesn't need a custom xlate routine. Signed-off-by: Eric Nelson Acked-by: Simon Glass Acked-by: Minkyu Kang --- drivers/gpio/s5p_gpio.c | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/drivers/gpio/s5p_gpio.c b/drivers/gpio/s5p_gpio.c index 0f22b238ba..377fed467f 100644 --- a/drivers/gpio/s5p_gpio.c +++ b/drivers/gpio/s5p_gpio.c @@ -13,7 +13,6 @@ #include #include #include -#include DECLARE_GLOBAL_DATA_PTR; @@ -276,22 +275,12 @@ static int exynos_gpio_get_function(struct udevice *dev, unsigned offset) return GPIOF_FUNC; } -static int exynos_gpio_xlate(struct udevice *dev, struct gpio_desc *desc, - struct fdtdec_phandle_args *args) -{ - desc->offset = args->args[0]; - desc->flags = args->args[1] & GPIO_ACTIVE_LOW ? GPIOD_ACTIVE_LOW : 0; - - return 0; -} - static const struct dm_gpio_ops gpio_exynos_ops = { .direction_input = exynos_gpio_direction_input, .direction_output = exynos_gpio_direction_output, .get_value = exynos_gpio_get_value, .set_value = exynos_gpio_set_value, .get_function = exynos_gpio_get_function, - .xlate = exynos_gpio_xlate, }; static int gpio_exynos_probe(struct udevice *dev) From e161356bffd5b6757a43b9c55a81903227ddd20c Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 1 May 2016 11:35:49 -0600 Subject: [PATCH 037/162] Revert "dm: sandbox: Drop the pre-DM host implementation" Bring this support back so that sandbox can be compiled with CONFIG_BLK. This allows sandbox to have greater build coverage during the block-device transition. This can be removed again later. This reverts commit 33cf727b1634dbd9cd68a6ebc444a88f053822d7. Signed-off-by: Simon Glass --- drivers/block/sandbox.c | 90 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 90 insertions(+) diff --git a/drivers/block/sandbox.c b/drivers/block/sandbox.c index 2d340efd32..6d41508d5c 100644 --- a/drivers/block/sandbox.c +++ b/drivers/block/sandbox.c @@ -17,6 +17,19 @@ DECLARE_GLOBAL_DATA_PTR; +#ifndef CONFIG_BLK +static struct host_block_dev host_devices[CONFIG_HOST_MAX_DEVICES]; + +static struct host_block_dev *find_host_device(int dev) +{ + if (dev >= 0 && dev < CONFIG_HOST_MAX_DEVICES) + return &host_devices[dev]; + + return NULL; +} +#endif + +#ifdef CONFIG_BLK static unsigned long host_block_read(struct udevice *dev, unsigned long start, lbaint_t blkcnt, void *buffer) @@ -24,6 +37,18 @@ static unsigned long host_block_read(struct udevice *dev, struct host_block_dev *host_dev = dev_get_priv(dev); struct blk_desc *block_dev = dev_get_uclass_platdata(dev); +#else +static unsigned long host_block_read(struct blk_desc *block_dev, + unsigned long start, lbaint_t blkcnt, + void *buffer) +{ + int dev = block_dev->devnum; + struct host_block_dev *host_dev = find_host_device(dev); + + if (!host_dev) + return -1; +#endif + if (os_lseek(host_dev->fd, start * block_dev->blksz, OS_SEEK_SET) == -1) { printf("ERROR: Invalid block %lx\n", start); @@ -35,12 +60,21 @@ static unsigned long host_block_read(struct udevice *dev, return -1; } +#ifdef CONFIG_BLK static unsigned long host_block_write(struct udevice *dev, unsigned long start, lbaint_t blkcnt, const void *buffer) { struct host_block_dev *host_dev = dev_get_priv(dev); struct blk_desc *block_dev = dev_get_uclass_platdata(dev); +#else +static unsigned long host_block_write(struct blk_desc *block_dev, + unsigned long start, lbaint_t blkcnt, + const void *buffer) +{ + int dev = block_dev->devnum; + struct host_block_dev *host_dev = find_host_device(dev); +#endif if (os_lseek(host_dev->fd, start * block_dev->blksz, OS_SEEK_SET) == -1) { @@ -53,6 +87,7 @@ static unsigned long host_block_write(struct udevice *dev, return -1; } +#ifdef CONFIG_BLK int host_dev_bind(int devnum, char *filename) { struct host_block_dev *host_dev; @@ -115,9 +150,51 @@ err: free(str); return ret; } +#else +int host_dev_bind(int dev, char *filename) +{ + struct host_block_dev *host_dev = find_host_device(dev); + + if (!host_dev) + return -1; + if (host_dev->blk_dev.priv) { + os_close(host_dev->fd); + host_dev->blk_dev.priv = NULL; + } + if (host_dev->filename) + free(host_dev->filename); + if (filename && *filename) { + host_dev->filename = strdup(filename); + } else { + host_dev->filename = NULL; + return 0; + } + + host_dev->fd = os_open(host_dev->filename, OS_O_RDWR); + if (host_dev->fd == -1) { + printf("Failed to access host backing file '%s'\n", + host_dev->filename); + return 1; + } + + struct blk_desc *blk_dev = &host_dev->blk_dev; + blk_dev->if_type = IF_TYPE_HOST; + blk_dev->priv = host_dev; + blk_dev->blksz = 512; + blk_dev->lba = os_lseek(host_dev->fd, 0, OS_SEEK_END) / blk_dev->blksz; + blk_dev->block_read = host_block_read; + blk_dev->block_write = host_block_write; + blk_dev->devnum = dev; + blk_dev->part_type = PART_TYPE_UNKNOWN; + part_init(blk_dev); + + return 0; +} +#endif int host_get_dev_err(int devnum, struct blk_desc **blk_devp) { +#ifdef CONFIG_BLK struct udevice *dev; int ret; @@ -125,6 +202,17 @@ int host_get_dev_err(int devnum, struct blk_desc **blk_devp) if (ret) return ret; *blk_devp = dev_get_uclass_platdata(dev); +#else + struct host_block_dev *host_dev = find_host_device(devnum); + + if (!host_dev) + return -ENODEV; + + if (!host_dev->blk_dev.priv) + return -ENOENT; + + *blk_devp = &host_dev->blk_dev; +#endif return 0; } @@ -139,6 +227,7 @@ struct blk_desc *host_get_dev(int dev) return blk_dev; } +#ifdef CONFIG_BLK static const struct blk_ops sandbox_host_blk_ops = { .read = host_block_read, .write = host_block_write, @@ -150,3 +239,4 @@ U_BOOT_DRIVER(sandbox_host_blk) = { .ops = &sandbox_host_blk_ops, .priv_auto_alloc_size = sizeof(struct host_block_dev), }; +#endif From f960ca0a5fde2d1ec673d335a06a0f408734b3b3 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 1 May 2016 11:35:50 -0600 Subject: [PATCH 038/162] dm: sandbox: Add a board for sandbox without CONFIG_BLK While the driver-model block device support is in progress, it is useful to build sandbox both with and without CONFIG_BLK. Add a separate board for the latter. Signed-off-by: Simon Glass --- board/sandbox/MAINTAINERS | 7 ++ configs/sandbox_noblk_defconfig | 168 ++++++++++++++++++++++++++++++++ 2 files changed, 175 insertions(+) create mode 100644 configs/sandbox_noblk_defconfig diff --git a/board/sandbox/MAINTAINERS b/board/sandbox/MAINTAINERS index 10d88a28a6..f5db773a47 100644 --- a/board/sandbox/MAINTAINERS +++ b/board/sandbox/MAINTAINERS @@ -4,3 +4,10 @@ S: Maintained F: board/sandbox/ F: include/configs/sandbox.h F: configs/sandbox_defconfig + +SANDBOX_NOBLK BOARD +M: Simon Glass +S: Maintained +F: board/sandbox/ +F: include/configs/sandbox.h +F: configs/sandbox_noblk_defconfig diff --git a/configs/sandbox_noblk_defconfig b/configs/sandbox_noblk_defconfig new file mode 100644 index 0000000000..93167c2f65 --- /dev/null +++ b/configs/sandbox_noblk_defconfig @@ -0,0 +1,168 @@ +CONFIG_SYS_MALLOC_F_LEN=0x2000 +CONFIG_PCI=y +CONFIG_DEFAULT_DEVICE_TREE="sandbox" +CONFIG_I8042_KEYB=y +CONFIG_FIT=y +CONFIG_FIT_VERBOSE=y +CONFIG_FIT_SIGNATURE=y +CONFIG_SPL_LOAD_FIT=y +CONFIG_BOOTSTAGE=y +CONFIG_BOOTSTAGE_REPORT=y +CONFIG_BOOTSTAGE_USER_COUNT=0x20 +CONFIG_BOOTSTAGE_FDT=y +CONFIG_BOOTSTAGE_STASH=y +CONFIG_BOOTSTAGE_STASH_ADDR=0x0 +CONFIG_BOOTSTAGE_STASH_SIZE=0x4096 +CONFIG_CONSOLE_RECORD=y +CONFIG_CONSOLE_RECORD_OUT_SIZE=0x1000 +CONFIG_HUSH_PARSER=y +CONFIG_CMD_CPU=y +CONFIG_CMD_LICENSE=y +CONFIG_CMD_BOOTZ=y +# CONFIG_CMD_ELF is not set +# CONFIG_CMD_IMLS is not set +CONFIG_CMD_ASKENV=y +CONFIG_CMD_GREPENV=y +CONFIG_LOOPW=y +CONFIG_CMD_MEMTEST=y +CONFIG_CMD_MX_CYCLIC=y +CONFIG_CMD_MEMINFO=y +CONFIG_CMD_DEMO=y +CONFIG_CMD_SF=y +CONFIG_CMD_SPI=y +CONFIG_CMD_I2C=y +CONFIG_CMD_USB=y +CONFIG_CMD_REMOTEPROC=y +CONFIG_CMD_GPIO=y +CONFIG_CMD_TFTPPUT=y +CONFIG_CMD_TFTPSRV=y +CONFIG_CMD_RARP=y +CONFIG_CMD_DHCP=y +CONFIG_CMD_MII=y +CONFIG_CMD_PING=y +CONFIG_CMD_CDP=y +CONFIG_CMD_SNTP=y +CONFIG_CMD_DNS=y +CONFIG_CMD_LINK_LOCAL=y +CONFIG_CMD_TIME=y +CONFIG_CMD_TIMER=y +CONFIG_CMD_SOUND=y +CONFIG_CMD_BOOTSTAGE=y +CONFIG_CMD_PMIC=y +CONFIG_CMD_REGULATOR=y +CONFIG_CMD_TPM=y +CONFIG_CMD_TPM_TEST=y +CONFIG_CMD_EXT2=y +CONFIG_CMD_EXT4=y +CONFIG_CMD_EXT4_WRITE=y +CONFIG_CMD_FAT=y +CONFIG_CMD_FS_GENERIC=y +CONFIG_OF_CONTROL=y +CONFIG_OF_HOSTFILE=y +CONFIG_NETCONSOLE=y +CONFIG_REGMAP=y +CONFIG_SPL_REGMAP=y +CONFIG_SYSCON=y +CONFIG_SPL_SYSCON=y +CONFIG_DEVRES=y +CONFIG_DEBUG_DEVRES=y +CONFIG_ADC=y +CONFIG_ADC_SANDBOX=y +CONFIG_CLK=y +CONFIG_CPU=y +CONFIG_DM_DEMO=y +CONFIG_DM_DEMO_SIMPLE=y +CONFIG_DM_DEMO_SHAPE=y +CONFIG_PM8916_GPIO=y +CONFIG_SANDBOX_GPIO=y +CONFIG_DM_I2C_COMPAT=y +CONFIG_I2C_CROS_EC_TUNNEL=y +CONFIG_I2C_CROS_EC_LDO=y +CONFIG_DM_I2C_GPIO=y +CONFIG_SYS_I2C_SANDBOX=y +CONFIG_I2C_MUX=y +CONFIG_SPL_I2C_MUX=y +CONFIG_I2C_ARB_GPIO_CHALLENGE=y +CONFIG_CROS_EC_KEYB=y +CONFIG_LED=y +CONFIG_LED_GPIO=y +CONFIG_CMD_CROS_EC=y +CONFIG_CROS_EC=y +CONFIG_CROS_EC_I2C=y +CONFIG_CROS_EC_LPC=y +CONFIG_CROS_EC_SANDBOX=y +CONFIG_CROS_EC_SPI=y +CONFIG_PWRSEQ=y +CONFIG_SPL_PWRSEQ=y +CONFIG_RESET=y +CONFIG_DM_MMC=y +CONFIG_SPI_FLASH_SANDBOX=y +CONFIG_SPI_FLASH=y +CONFIG_SPI_FLASH_ATMEL=y +CONFIG_SPI_FLASH_EON=y +CONFIG_SPI_FLASH_GIGADEVICE=y +CONFIG_SPI_FLASH_MACRONIX=y +CONFIG_SPI_FLASH_SPANSION=y +CONFIG_SPI_FLASH_STMICRO=y +CONFIG_SPI_FLASH_SST=y +CONFIG_SPI_FLASH_WINBOND=y +CONFIG_DM_ETH=y +CONFIG_DM_PCI=y +CONFIG_DM_PCI_COMPAT=y +CONFIG_PCI_SANDBOX=y +CONFIG_PINCTRL=y +CONFIG_PINCONF=y +CONFIG_ROCKCHIP_PINCTRL=y +CONFIG_ROCKCHIP_3036_PINCTRL=y +CONFIG_PINCTRL_SANDBOX=y +CONFIG_DM_PMIC=y +CONFIG_PMIC_ACT8846=y +CONFIG_DM_PMIC_PFUZE100=y +CONFIG_DM_PMIC_MAX77686=y +CONFIG_PMIC_PM8916=y +CONFIG_PMIC_RK808=y +CONFIG_PMIC_S2MPS11=y +CONFIG_DM_PMIC_SANDBOX=y +CONFIG_PMIC_S5M8767=y +CONFIG_PMIC_TPS65090=y +CONFIG_DM_REGULATOR=y +CONFIG_REGULATOR_ACT8846=y +CONFIG_DM_REGULATOR_PFUZE100=y +CONFIG_DM_REGULATOR_MAX77686=y +CONFIG_DM_REGULATOR_FIXED=y +CONFIG_REGULATOR_RK808=y +CONFIG_REGULATOR_S5M8767=y +CONFIG_DM_REGULATOR_SANDBOX=y +CONFIG_REGULATOR_TPS65090=y +CONFIG_RAM=y +CONFIG_REMOTEPROC_SANDBOX=y +CONFIG_DM_RTC=y +CONFIG_SANDBOX_SERIAL=y +CONFIG_SOUND=y +CONFIG_SOUND_SANDBOX=y +CONFIG_SANDBOX_SPI=y +CONFIG_SPMI=y +CONFIG_SPMI_SANDBOX=y +CONFIG_TIMER=y +CONFIG_TIMER_EARLY=y +CONFIG_SANDBOX_TIMER=y +CONFIG_TPM_TIS_SANDBOX=y +CONFIG_USB=y +CONFIG_DM_USB=y +CONFIG_USB_EMUL=y +CONFIG_USB_STORAGE=y +CONFIG_USB_KEYBOARD=y +CONFIG_SYS_USB_EVENT_POLL=y +CONFIG_DM_VIDEO=y +CONFIG_CONSOLE_ROTATION=y +CONFIG_CONSOLE_TRUETYPE=y +CONFIG_CONSOLE_TRUETYPE_CANTORAONE=y +CONFIG_VIDEO_SANDBOX_SDL=y +CONFIG_CMD_DHRYSTONE=y +CONFIG_TPM=y +CONFIG_LZ4=y +CONFIG_ERRNO_STR=y +CONFIG_UNIT_TEST=y +CONFIG_UT_TIME=y +CONFIG_UT_DM=y +CONFIG_UT_ENV=y From cf63084492377108698619f6d33967af2119e584 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 1 May 2016 11:35:51 -0600 Subject: [PATCH 039/162] pci: Drop CONFIG_SYS_SCSI_SCAN_BUS_REVERSE This option is not used by any board. Drop it. Signed-off-by: Simon Glass Reviewed-by: Bin Meng --- drivers/pci/pci.c | 4 ---- include/configs/MPC8641HPCN.h | 2 -- include/configs/sbc8641d.h | 2 -- 3 files changed, 8 deletions(-) diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 461908941d..4b73a0ff9c 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -175,11 +175,7 @@ pci_dev_t pci_find_devices(struct pci_device_id *ids, int index) int bus; for (hose = pci_get_hose_head(); hose; hose = hose->next) { -#ifdef CONFIG_SYS_SCSI_SCAN_BUS_REVERSE - for (bus = hose->last_busno; bus >= hose->first_busno; bus--) { -#else for (bus = hose->first_busno; bus <= hose->last_busno; bus++) { -#endif bdf = pci_hose_find_devices(hose, bus, ids, &index); if (bdf != -1) return bdf; diff --git a/include/configs/MPC8641HPCN.h b/include/configs/MPC8641HPCN.h index 2f94c8214e..5e23007d8d 100644 --- a/include/configs/MPC8641HPCN.h +++ b/include/configs/MPC8641HPCN.h @@ -354,8 +354,6 @@ extern unsigned long get_board_sys_clk(unsigned long dummy); #define CONFIG_PCI_SCAN_SHOW /* show pci devices on startup */ -#undef CONFIG_SYS_SCSI_SCAN_BUS_REVERSE - #define CONFIG_PCI_PNP /* do pci plug-and-play */ #undef CONFIG_EEPRO100 diff --git a/include/configs/sbc8641d.h b/include/configs/sbc8641d.h index a7c7aef71a..c9970f1f3e 100644 --- a/include/configs/sbc8641d.h +++ b/include/configs/sbc8641d.h @@ -297,8 +297,6 @@ #define CONFIG_PCI_SCAN_SHOW /* show pci devices on startup */ -#undef CONFIG_SYS_SCSI_SCAN_BUS_REVERSE - #define CONFIG_PCI_PNP /* do pci plug-and-play */ #undef CONFIG_EEPRO100 From a219639d4216e59a0c55f0b7d2c8a21f9cb0bb06 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 1 May 2016 11:35:52 -0600 Subject: [PATCH 040/162] dm: Rename disk uclass to ahci This started as 'ahci' and was renamed to 'disk' during code review. But it seems that this is too generic. Now that we have a 'blk' uclass, we can use that as the generic piece, and revert to ahci for this. Signed-off-by: Simon Glass --- arch/x86/Kconfig | 3 +++ arch/x86/cpu/broadwell/sata.c | 2 +- arch/x86/cpu/intel_common/cpu.c | 2 +- arch/x86/cpu/ivybridge/bd82x6x.c | 2 +- arch/x86/cpu/ivybridge/sata.c | 2 +- drivers/block/Kconfig | 5 ++--- drivers/block/Makefile | 2 +- drivers/block/{disk-uclass.c => ahci-uclass.c} | 6 +++--- include/dm/uclass-id.h | 2 +- 9 files changed, 14 insertions(+), 12 deletions(-) rename drivers/block/{disk-uclass.c => ahci-uclass.c} (72%) diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 4ef27dc87a..396023eee8 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -47,6 +47,9 @@ source "arch/x86/cpu/queensbay/Kconfig" # architecture-specific options below +config AHCI + default y + config SYS_MALLOC_F_LEN default 0x800 diff --git a/arch/x86/cpu/broadwell/sata.c b/arch/x86/cpu/broadwell/sata.c index dfb8486d06..2e4708262c 100644 --- a/arch/x86/cpu/broadwell/sata.c +++ b/arch/x86/cpu/broadwell/sata.c @@ -261,7 +261,7 @@ static const struct udevice_id broadwell_ahci_ids[] = { U_BOOT_DRIVER(ahci_broadwell_drv) = { .name = "ahci_broadwell", - .id = UCLASS_DISK, + .id = UCLASS_AHCI, .of_match = broadwell_ahci_ids, .ofdata_to_platdata = broadwell_sata_ofdata_to_platdata, .probe = broadwell_sata_probe, diff --git a/arch/x86/cpu/intel_common/cpu.c b/arch/x86/cpu/intel_common/cpu.c index 93e4505e4d..0fdef6f369 100644 --- a/arch/x86/cpu/intel_common/cpu.c +++ b/arch/x86/cpu/intel_common/cpu.c @@ -58,7 +58,7 @@ int cpu_common_init(void) return -ENODEV; /* Cause the SATA device to do its early init */ - uclass_first_device(UCLASS_DISK, &dev); + uclass_first_device(UCLASS_AHCI, &dev); return 0; } diff --git a/arch/x86/cpu/ivybridge/bd82x6x.c b/arch/x86/cpu/ivybridge/bd82x6x.c index 4c039ac9c6..5b58d6c427 100644 --- a/arch/x86/cpu/ivybridge/bd82x6x.c +++ b/arch/x86/cpu/ivybridge/bd82x6x.c @@ -162,7 +162,7 @@ static int bd82x6x_probe(struct udevice *dev) return 0; /* Cause the SATA device to do its init */ - uclass_first_device(UCLASS_DISK, &dev); + uclass_first_device(UCLASS_AHCI, &dev); ret = syscon_get_by_driver_data(X86_SYSCON_GMA, &gma_dev); if (ret) diff --git a/arch/x86/cpu/ivybridge/sata.c b/arch/x86/cpu/ivybridge/sata.c index c3d1057c29..1ce81959e3 100644 --- a/arch/x86/cpu/ivybridge/sata.c +++ b/arch/x86/cpu/ivybridge/sata.c @@ -233,7 +233,7 @@ static const struct udevice_id bd82x6x_ahci_ids[] = { U_BOOT_DRIVER(ahci_ivybridge_drv) = { .name = "ahci_ivybridge", - .id = UCLASS_DISK, + .id = UCLASS_AHCI, .of_match = bd82x6x_ahci_ids, .probe = bd82x6x_sata_probe, }; diff --git a/drivers/block/Kconfig b/drivers/block/Kconfig index fcc9ccdd7f..80eea84dc2 100644 --- a/drivers/block/Kconfig +++ b/drivers/block/Kconfig @@ -9,10 +9,9 @@ config BLK be partitioned into several areas, called 'partitions' in U-Boot. A filesystem can be placed in each partition. -config DISK - bool "Support disk controllers with driver model" +config AHCI + bool "Support SATA controllers with driver model" depends on DM - default y if DM help This enables a uclass for disk controllers in U-Boot. Various driver types can use this, such as AHCI/SATA. It does not provide any standard diff --git a/drivers/block/Makefile b/drivers/block/Makefile index a43492f208..b832ae18ac 100644 --- a/drivers/block/Makefile +++ b/drivers/block/Makefile @@ -7,7 +7,7 @@ obj-$(CONFIG_BLK) += blk-uclass.o -obj-$(CONFIG_DISK) += disk-uclass.o +obj-$(CONFIG_AHCI) += ahci-uclass.o obj-$(CONFIG_SCSI_AHCI) += ahci.o obj-$(CONFIG_DWC_AHSATA) += dwc_ahsata.o obj-$(CONFIG_FSL_SATA) += fsl_sata.o diff --git a/drivers/block/disk-uclass.c b/drivers/block/ahci-uclass.c similarity index 72% rename from drivers/block/disk-uclass.c rename to drivers/block/ahci-uclass.c index d665b3505a..7b8c32699f 100644 --- a/drivers/block/disk-uclass.c +++ b/drivers/block/ahci-uclass.c @@ -8,7 +8,7 @@ #include #include -UCLASS_DRIVER(disk) = { - .id = UCLASS_DISK, - .name = "disk", +UCLASS_DRIVER(ahci) = { + .id = UCLASS_AHCI, + .name = "ahci", }; diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h index cbf9b2ca23..a5cf6e201c 100644 --- a/include/dm/uclass-id.h +++ b/include/dm/uclass-id.h @@ -26,11 +26,11 @@ enum uclass_id { /* U-Boot uclasses start here - in alphabetical order */ UCLASS_ADC, /* Analog-to-digital converter */ + UCLASS_AHCI, /* SATA disk controller */ UCLASS_BLK, /* Block device */ UCLASS_CLK, /* Clock source, e.g. used by peripherals */ UCLASS_CPU, /* CPU, typically part of an SoC */ UCLASS_CROS_EC, /* Chrome OS EC */ - UCLASS_DISK, /* Disk controller, e.g. SATA */ UCLASS_DISPLAY, /* Display (e.g. DisplayPort, HDMI) */ UCLASS_DMA, /* Direct Memory Access */ UCLASS_RAM, /* RAM controller */ From 709e98b7b2461c2535d4ac2bb0311c3b3f53dbbb Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 1 May 2016 11:35:53 -0600 Subject: [PATCH 041/162] Allow iotrace byte access to use an address of any size If an address is used with readb() and writeb() which is smaller than the expected size (e.g. 32-bit value on a machine with 64-bit addresses), a warning results. Fix this by adding a cast. Signed-off-by: Simon Glass --- include/iotrace.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/include/iotrace.h b/include/iotrace.h index 9bd1f167ab..e4ceb61805 100644 --- a/include/iotrace.h +++ b/include/iotrace.h @@ -31,10 +31,11 @@ #define writew(val, addr) iotrace_writew(val, (const void *)(addr)) #undef readb -#define readb(addr) iotrace_readb((const void *)(addr)) +#define readb(addr) iotrace_readb((const void *)(uintptr_t)addr) #undef writeb -#define writeb(val, addr) iotrace_writeb(val, (const void *)(addr)) +#define writeb(val, addr) \ + iotrace_writeb(val, (const void *)(uintptr_t)addr) #endif From e54094f2f9e812ae7b0d2ab2353ca11c0502849a Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 1 May 2016 11:35:54 -0600 Subject: [PATCH 042/162] sandbox: Add string and 16-bit I/O functions Add outsw() and insw() functions for sandbox, as these are needed by the IDE code. The functions will not do anything useful if called, but allow the code to be compiled. Also add out16() and in16(), required by systemace. Signed-off-by: Simon Glass --- arch/sandbox/include/asm/io.h | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/arch/sandbox/include/asm/io.h b/arch/sandbox/include/asm/io.h index b87ee19427..69196329d7 100644 --- a/arch/sandbox/include/asm/io.h +++ b/arch/sandbox/include/asm/io.h @@ -56,6 +56,21 @@ void outl(unsigned int value, unsigned int addr); void outw(unsigned int value, unsigned int addr); void outb(unsigned int value, unsigned int addr); +static inline void _insw(volatile u16 *port, void *buf, int ns) +{ +} + +static inline void _outsw(volatile u16 *port, const void *buf, int ns) +{ +} + +#define insw(port, buf, ns) _insw((u16 *)port, buf, ns) +#define outsw(port, buf, ns) _outsw((u16 *)port, buf, ns) + +/* For systemace.c */ +#define out16(addr, val) +#define in16(addr) 0 + #include #include From 84d39cbd30a49390457232b44031e95abfa46e77 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 1 May 2016 11:35:55 -0600 Subject: [PATCH 043/162] sandbox: Add dummy SCSI functions Add some functions needed by the SCSI code. This allows it to be compiled for sandbox, thus increasing build coverage. Signed-off-by: Simon Glass --- drivers/block/Makefile | 2 +- drivers/block/sandbox_scsi.c | 29 +++++++++++++++++++++++++++++ 2 files changed, 30 insertions(+), 1 deletion(-) create mode 100644 drivers/block/sandbox_scsi.c diff --git a/drivers/block/Makefile b/drivers/block/Makefile index b832ae18ac..3b48eac5e7 100644 --- a/drivers/block/Makefile +++ b/drivers/block/Makefile @@ -22,7 +22,7 @@ obj-$(CONFIG_SATA_MV) += sata_mv.o obj-$(CONFIG_SATA_SIL3114) += sata_sil3114.o obj-$(CONFIG_SATA_SIL) += sata_sil.o obj-$(CONFIG_IDE_SIL680) += sil680.o -obj-$(CONFIG_SANDBOX) += sandbox.o +obj-$(CONFIG_SANDBOX) += sandbox.o sandbox_scsi.o obj-$(CONFIG_SCSI_SYM53C8XX) += sym53c8xx.o obj-$(CONFIG_SYSTEMACE) += systemace.o obj-$(CONFIG_BLOCK_CACHE) += blkcache.o diff --git a/drivers/block/sandbox_scsi.c b/drivers/block/sandbox_scsi.c new file mode 100644 index 0000000000..ad961bd225 --- /dev/null +++ b/drivers/block/sandbox_scsi.c @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2015 Google, Inc + * Written by Simon Glass + * + * SPDX-License-Identifier: GPL-2.0+ + * + * This file contains dummy implementations of SCSI functions requried so + * that CONFIG_SCSI can be enabled for sandbox. + */ + +#include +#include + +void scsi_bus_reset(void) +{ +} + +void scsi_init(void) +{ +} + +int scsi_exec(ccb *pccb) +{ + return 0; +} + +void scsi_print_error(ccb *pccb) +{ +} From a31e2c93cb9eb1d4fe732b5586316235dad537ea Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 1 May 2016 11:35:56 -0600 Subject: [PATCH 044/162] sandbox: Add dummy SATA functions Add some functions needed by the SATA code. This allows it to be compiled for sandbox, thus increasing build coverage. Signed-off-by: Simon Glass --- drivers/block/Makefile | 2 +- drivers/block/sata_sandbox.c | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 1 deletion(-) create mode 100644 drivers/block/sata_sandbox.c diff --git a/drivers/block/Makefile b/drivers/block/Makefile index 3b48eac5e7..3f759341d4 100644 --- a/drivers/block/Makefile +++ b/drivers/block/Makefile @@ -22,7 +22,7 @@ obj-$(CONFIG_SATA_MV) += sata_mv.o obj-$(CONFIG_SATA_SIL3114) += sata_sil3114.o obj-$(CONFIG_SATA_SIL) += sata_sil.o obj-$(CONFIG_IDE_SIL680) += sil680.o -obj-$(CONFIG_SANDBOX) += sandbox.o sandbox_scsi.o +obj-$(CONFIG_SANDBOX) += sandbox.o sandbox_scsi.o sata_sandbox.o obj-$(CONFIG_SCSI_SYM53C8XX) += sym53c8xx.o obj-$(CONFIG_SYSTEMACE) += systemace.o obj-$(CONFIG_BLOCK_CACHE) += blkcache.o diff --git a/drivers/block/sata_sandbox.c b/drivers/block/sata_sandbox.c new file mode 100644 index 0000000000..bd967d290c --- /dev/null +++ b/drivers/block/sata_sandbox.c @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2015 Google, Inc + * Written by Simon Glass + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include + +int init_sata(int dev) +{ + return 0; +} + +int reset_sata(int dev) +{ + return 0; +} + +int scan_sata(int dev) +{ + return 0; +} + +ulong sata_read(int dev, ulong blknr, lbaint_t blkcnt, void *buffer) +{ + return 0; +} + +ulong sata_write(int dev, ulong blknr, lbaint_t blkcnt, const void *buffer) +{ + return 0; +} From 73a9cfde783421aa7355143bc5b535ae81126d2c Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 1 May 2016 11:35:57 -0600 Subject: [PATCH 045/162] dm: scsi: Remove the forward declarations Reorder the code to avoid needing forward declarations. Signed-off-by: Simon Glass --- cmd/scsi.c | 656 ++++++++++++++++++++++++++--------------------------- 1 file changed, 317 insertions(+), 339 deletions(-) diff --git a/cmd/scsi.c b/cmd/scsi.c index 8991125c66..9ba070f8b9 100644 --- a/cmd/scsi.c +++ b/cmd/scsi.c @@ -50,130 +50,230 @@ static int scsi_curr_dev; /* current device */ static struct blk_desc scsi_dev_desc[CONFIG_SYS_SCSI_MAX_DEVICE]; -/******************************************************************************** - * forward declerations of some Setup Routines +/**************************************************************************************** + * scsi_read */ -void scsi_setup_test_unit_ready(ccb * pccb); -void scsi_setup_read6(ccb * pccb, lbaint_t start, unsigned short blocks); -void scsi_setup_read_ext(ccb * pccb, lbaint_t start, unsigned short blocks); -void scsi_setup_read16(ccb * pccb, lbaint_t start, unsigned long blocks); -static void scsi_setup_write_ext(ccb *pccb, lbaint_t start, - unsigned short blocks); -void scsi_setup_inquiry(ccb * pccb); -void scsi_ident_cpy (unsigned char *dest, unsigned char *src, unsigned int len); +/* almost the maximum amount of the scsi_ext command.. */ +#define SCSI_MAX_READ_BLK 0xFFFF +#define SCSI_LBA48_READ 0xFFFFFFF - -static int scsi_read_capacity(ccb *pccb, lbaint_t *capacity, - unsigned long *blksz); -static ulong scsi_read(struct blk_desc *block_dev, lbaint_t blknr, - lbaint_t blkcnt, void *buffer); -static ulong scsi_write(struct blk_desc *block_dev, lbaint_t blknr, - lbaint_t blkcnt, const void *buffer); - - -/********************************************************************************* - * (re)-scan the scsi bus and reports scsi device info - * to the user if mode = 1 - */ -void scsi_scan(int mode) +#ifdef CONFIG_SYS_64BIT_LBA +void scsi_setup_read16(ccb * pccb, lbaint_t start, unsigned long blocks) { - unsigned char i,perq,modi,lun; - lbaint_t capacity; - unsigned long blksz; - ccb* pccb=(ccb *)&tempccb; - - if(mode==1) { - printf("scanning bus for devices...\n"); - } - for(i=0;itarget=i; - for(lun=0;lunlun=lun; - pccb->pdata=(unsigned char *)&tempbuff; - pccb->datalen=512; - scsi_setup_inquiry(pccb); - if (scsi_exec(pccb) != true) { - if(pccb->contr_stat==SCSI_SEL_TIME_OUT) { - debug ("Selection timeout ID %d\n",pccb->target); - continue; /* selection timeout => assuming no device present */ - } - scsi_print_error(pccb); - continue; - } - perq=tempbuff[0]; - modi=tempbuff[1]; - if((perq & 0x1f)==0x1f) { - continue; /* skip unknown devices */ - } - if((modi&0x80)==0x80) /* drive is removable */ - scsi_dev_desc[scsi_max_devs].removable=true; - /* get info for this device */ - scsi_ident_cpy((unsigned char *)&scsi_dev_desc[scsi_max_devs].vendor[0], - &tempbuff[8], 8); - scsi_ident_cpy((unsigned char *)&scsi_dev_desc[scsi_max_devs].product[0], - &tempbuff[16], 16); - scsi_ident_cpy((unsigned char *)&scsi_dev_desc[scsi_max_devs].revision[0], - &tempbuff[32], 4); - scsi_dev_desc[scsi_max_devs].target=pccb->target; - scsi_dev_desc[scsi_max_devs].lun=pccb->lun; - - pccb->datalen=0; - scsi_setup_test_unit_ready(pccb); - if (scsi_exec(pccb) != true) { - if (scsi_dev_desc[scsi_max_devs].removable == true) { - scsi_dev_desc[scsi_max_devs].type=perq; - goto removable; - } - scsi_print_error(pccb); - continue; - } - if (scsi_read_capacity(pccb, &capacity, &blksz)) { - scsi_print_error(pccb); - continue; - } - scsi_dev_desc[scsi_max_devs].lba=capacity; - scsi_dev_desc[scsi_max_devs].blksz=blksz; - scsi_dev_desc[scsi_max_devs].log2blksz = - LOG2(scsi_dev_desc[scsi_max_devs].blksz); - scsi_dev_desc[scsi_max_devs].type=perq; - part_init(&scsi_dev_desc[scsi_max_devs]); -removable: - if(mode==1) { - printf (" Device %d: ", scsi_max_devs); - dev_print(&scsi_dev_desc[scsi_max_devs]); - } /* if mode */ - scsi_max_devs++; - } /* next LUN */ - } - if(scsi_max_devs>0) - scsi_curr_dev=0; - else - scsi_curr_dev = -1; - - printf("Found %d device(s).\n", scsi_max_devs); -#ifndef CONFIG_SPL_BUILD - setenv_ulong("scsidevs", scsi_max_devs); + pccb->cmd[0] = SCSI_READ16; + pccb->cmd[1] = pccb->lun<<5; + pccb->cmd[2] = ((unsigned char) (start >> 56)) & 0xff; + pccb->cmd[3] = ((unsigned char) (start >> 48)) & 0xff; + pccb->cmd[4] = ((unsigned char) (start >> 40)) & 0xff; + pccb->cmd[5] = ((unsigned char) (start >> 32)) & 0xff; + pccb->cmd[6] = ((unsigned char) (start >> 24)) & 0xff; + pccb->cmd[7] = ((unsigned char) (start >> 16)) & 0xff; + pccb->cmd[8] = ((unsigned char) (start >> 8)) & 0xff; + pccb->cmd[9] = ((unsigned char) (start)) & 0xff; + pccb->cmd[10] = 0; + pccb->cmd[11] = ((unsigned char) (blocks >> 24)) & 0xff; + pccb->cmd[12] = ((unsigned char) (blocks >> 16)) & 0xff; + pccb->cmd[13] = ((unsigned char) (blocks >> 8)) & 0xff; + pccb->cmd[14] = (unsigned char) blocks & 0xff; + pccb->cmd[15] = 0; + pccb->cmdlen = 16; + pccb->msgout[0] = SCSI_IDENTIFY; /* NOT USED */ + debug ("scsi_setup_read16: cmd: %02X %02X " + "startblk %02X%02X%02X%02X%02X%02X%02X%02X " + "blccnt %02X%02X%02X%02X\n", + pccb->cmd[0], pccb->cmd[1], + pccb->cmd[2], pccb->cmd[3], pccb->cmd[4], pccb->cmd[5], + pccb->cmd[6], pccb->cmd[7], pccb->cmd[8], pccb->cmd[9], + pccb->cmd[11], pccb->cmd[12], pccb->cmd[13], pccb->cmd[14]); +} #endif + +void scsi_setup_read_ext(ccb * pccb, lbaint_t start, unsigned short blocks) +{ + pccb->cmd[0]=SCSI_READ10; + pccb->cmd[1]=pccb->lun<<5; + pccb->cmd[2]=((unsigned char) (start>>24))&0xff; + pccb->cmd[3]=((unsigned char) (start>>16))&0xff; + pccb->cmd[4]=((unsigned char) (start>>8))&0xff; + pccb->cmd[5]=((unsigned char) (start))&0xff; + pccb->cmd[6]=0; + pccb->cmd[7]=((unsigned char) (blocks>>8))&0xff; + pccb->cmd[8]=(unsigned char) blocks & 0xff; + pccb->cmd[6]=0; + pccb->cmdlen=10; + pccb->msgout[0]=SCSI_IDENTIFY; /* NOT USED */ + debug ("scsi_setup_read_ext: cmd: %02X %02X startblk %02X%02X%02X%02X blccnt %02X%02X\n", + pccb->cmd[0],pccb->cmd[1], + pccb->cmd[2],pccb->cmd[3],pccb->cmd[4],pccb->cmd[5], + pccb->cmd[7],pccb->cmd[8]); +} + +void scsi_setup_write_ext(ccb *pccb, lbaint_t start, unsigned short blocks) +{ + pccb->cmd[0] = SCSI_WRITE10; + pccb->cmd[1] = pccb->lun << 5; + pccb->cmd[2] = ((unsigned char) (start>>24)) & 0xff; + pccb->cmd[3] = ((unsigned char) (start>>16)) & 0xff; + pccb->cmd[4] = ((unsigned char) (start>>8)) & 0xff; + pccb->cmd[5] = ((unsigned char) (start)) & 0xff; + pccb->cmd[6] = 0; + pccb->cmd[7] = ((unsigned char) (blocks>>8)) & 0xff; + pccb->cmd[8] = (unsigned char)blocks & 0xff; + pccb->cmd[9] = 0; + pccb->cmdlen = 10; + pccb->msgout[0] = SCSI_IDENTIFY; /* NOT USED */ + debug("%s: cmd: %02X %02X startblk %02X%02X%02X%02X blccnt %02X%02X\n", + __func__, + pccb->cmd[0], pccb->cmd[1], + pccb->cmd[2], pccb->cmd[3], pccb->cmd[4], pccb->cmd[5], + pccb->cmd[7], pccb->cmd[8]); +} + +void scsi_setup_read6(ccb * pccb, lbaint_t start, unsigned short blocks) +{ + pccb->cmd[0]=SCSI_READ6; + pccb->cmd[1]=pccb->lun<<5 | (((unsigned char)(start>>16))&0x1f); + pccb->cmd[2]=((unsigned char) (start>>8))&0xff; + pccb->cmd[3]=((unsigned char) (start))&0xff; + pccb->cmd[4]=(unsigned char) blocks & 0xff; + pccb->cmd[5]=0; + pccb->cmdlen=6; + pccb->msgout[0]=SCSI_IDENTIFY; /* NOT USED */ + debug ("scsi_setup_read6: cmd: %02X %02X startblk %02X%02X blccnt %02X\n", + pccb->cmd[0],pccb->cmd[1], + pccb->cmd[2],pccb->cmd[3],pccb->cmd[4]); +} + + +void scsi_setup_inquiry(ccb * pccb) +{ + pccb->cmd[0]=SCSI_INQUIRY; + pccb->cmd[1]=pccb->lun<<5; + pccb->cmd[2]=0; + pccb->cmd[3]=0; + if(pccb->datalen>255) + pccb->cmd[4]=255; + else + pccb->cmd[4]=(unsigned char)pccb->datalen; + pccb->cmd[5]=0; + pccb->cmdlen=6; + pccb->msgout[0]=SCSI_IDENTIFY; /* NOT USED */ +} + +static ulong scsi_read(struct blk_desc *block_dev, lbaint_t blknr, + lbaint_t blkcnt, void *buffer) +{ + int device = block_dev->devnum; + lbaint_t start, blks; + uintptr_t buf_addr; + unsigned short smallblks = 0; + ccb* pccb=(ccb *)&tempccb; + device&=0xff; + /* Setup device + */ + pccb->target=scsi_dev_desc[device].target; + pccb->lun=scsi_dev_desc[device].lun; + buf_addr=(unsigned long)buffer; + start=blknr; + blks=blkcnt; + debug("\nscsi_read: dev %d startblk " LBAF + ", blccnt " LBAF " buffer %lx\n", + device, start, blks, (unsigned long)buffer); + do { + pccb->pdata=(unsigned char *)buf_addr; +#ifdef CONFIG_SYS_64BIT_LBA + if (start > SCSI_LBA48_READ) { + unsigned long blocks; + blocks = min_t(lbaint_t, blks, SCSI_MAX_READ_BLK); + pccb->datalen = scsi_dev_desc[device].blksz * blocks; + scsi_setup_read16(pccb, start, blocks); + start += blocks; + blks -= blocks; + } else +#endif + if (blks > SCSI_MAX_READ_BLK) { + pccb->datalen=scsi_dev_desc[device].blksz * SCSI_MAX_READ_BLK; + smallblks=SCSI_MAX_READ_BLK; + scsi_setup_read_ext(pccb,start,smallblks); + start+=SCSI_MAX_READ_BLK; + blks-=SCSI_MAX_READ_BLK; + } + else { + pccb->datalen=scsi_dev_desc[device].blksz * blks; + smallblks=(unsigned short) blks; + scsi_setup_read_ext(pccb,start,smallblks); + start+=blks; + blks=0; + } + debug("scsi_read_ext: startblk " LBAF + ", blccnt %x buffer %" PRIXPTR "\n", + start, smallblks, buf_addr); + if (scsi_exec(pccb) != true) { + scsi_print_error(pccb); + blkcnt-=blks; + break; + } + buf_addr+=pccb->datalen; + } while(blks!=0); + debug("scsi_read_ext: end startblk " LBAF + ", blccnt %x buffer %" PRIXPTR "\n", start, smallblks, buf_addr); + return(blkcnt); +} + +/******************************************************************************* + * scsi_write + */ + +/* Almost the maximum amount of the scsi_ext command.. */ +#define SCSI_MAX_WRITE_BLK 0xFFFF + +static ulong scsi_write(struct blk_desc *block_dev, lbaint_t blknr, + lbaint_t blkcnt, const void *buffer) +{ + int device = block_dev->devnum; + lbaint_t start, blks; + uintptr_t buf_addr; + unsigned short smallblks; + ccb* pccb = (ccb *)&tempccb; + device &= 0xff; + /* Setup device + */ + pccb->target = scsi_dev_desc[device].target; + pccb->lun = scsi_dev_desc[device].lun; + buf_addr = (unsigned long)buffer; + start = blknr; + blks = blkcnt; + debug("\n%s: dev %d startblk " LBAF ", blccnt " LBAF " buffer %lx\n", + __func__, device, start, blks, (unsigned long)buffer); + do { + pccb->pdata = (unsigned char *)buf_addr; + if (blks > SCSI_MAX_WRITE_BLK) { + pccb->datalen = (scsi_dev_desc[device].blksz * + SCSI_MAX_WRITE_BLK); + smallblks = SCSI_MAX_WRITE_BLK; + scsi_setup_write_ext(pccb, start, smallblks); + start += SCSI_MAX_WRITE_BLK; + blks -= SCSI_MAX_WRITE_BLK; + } else { + pccb->datalen = scsi_dev_desc[device].blksz * blks; + smallblks = (unsigned short)blks; + scsi_setup_write_ext(pccb, start, smallblks); + start += blks; + blks = 0; + } + debug("%s: startblk " LBAF ", blccnt %x buffer %" PRIXPTR "\n", + __func__, start, smallblks, buf_addr); + if (scsi_exec(pccb) != true) { + scsi_print_error(pccb); + blkcnt -= blks; + break; + } + buf_addr += pccb->datalen; + } while (blks != 0); + debug("%s: end startblk " LBAF ", blccnt %x buffer %" PRIXPTR "\n", + __func__, start, smallblks, buf_addr); + return blkcnt; } int scsi_get_disk_count(void) @@ -390,129 +490,6 @@ U_BOOT_CMD( ); #endif -/**************************************************************************************** - * scsi_read - */ - -/* almost the maximum amount of the scsi_ext command.. */ -#define SCSI_MAX_READ_BLK 0xFFFF -#define SCSI_LBA48_READ 0xFFFFFFF - -static ulong scsi_read(struct blk_desc *block_dev, lbaint_t blknr, - lbaint_t blkcnt, void *buffer) -{ - int device = block_dev->devnum; - lbaint_t start, blks; - uintptr_t buf_addr; - unsigned short smallblks = 0; - ccb* pccb=(ccb *)&tempccb; - device&=0xff; - /* Setup device - */ - pccb->target=scsi_dev_desc[device].target; - pccb->lun=scsi_dev_desc[device].lun; - buf_addr=(unsigned long)buffer; - start=blknr; - blks=blkcnt; - debug("\nscsi_read: dev %d startblk " LBAF - ", blccnt " LBAF " buffer %lx\n", - device, start, blks, (unsigned long)buffer); - do { - pccb->pdata=(unsigned char *)buf_addr; -#ifdef CONFIG_SYS_64BIT_LBA - if (start > SCSI_LBA48_READ) { - unsigned long blocks; - blocks = min_t(lbaint_t, blks, SCSI_MAX_READ_BLK); - pccb->datalen = scsi_dev_desc[device].blksz * blocks; - scsi_setup_read16(pccb, start, blocks); - start += blocks; - blks -= blocks; - } else -#endif - if (blks > SCSI_MAX_READ_BLK) { - pccb->datalen=scsi_dev_desc[device].blksz * SCSI_MAX_READ_BLK; - smallblks=SCSI_MAX_READ_BLK; - scsi_setup_read_ext(pccb,start,smallblks); - start+=SCSI_MAX_READ_BLK; - blks-=SCSI_MAX_READ_BLK; - } - else { - pccb->datalen=scsi_dev_desc[device].blksz * blks; - smallblks=(unsigned short) blks; - scsi_setup_read_ext(pccb,start,smallblks); - start+=blks; - blks=0; - } - debug("scsi_read_ext: startblk " LBAF - ", blccnt %x buffer %" PRIXPTR "\n", - start, smallblks, buf_addr); - if (scsi_exec(pccb) != true) { - scsi_print_error(pccb); - blkcnt-=blks; - break; - } - buf_addr+=pccb->datalen; - } while(blks!=0); - debug("scsi_read_ext: end startblk " LBAF - ", blccnt %x buffer %" PRIXPTR "\n", start, smallblks, buf_addr); - return(blkcnt); -} - -/******************************************************************************* - * scsi_write - */ - -/* Almost the maximum amount of the scsi_ext command.. */ -#define SCSI_MAX_WRITE_BLK 0xFFFF - -static ulong scsi_write(struct blk_desc *block_dev, lbaint_t blknr, - lbaint_t blkcnt, const void *buffer) -{ - int device = block_dev->devnum; - lbaint_t start, blks; - uintptr_t buf_addr; - unsigned short smallblks; - ccb* pccb = (ccb *)&tempccb; - device &= 0xff; - /* Setup device - */ - pccb->target = scsi_dev_desc[device].target; - pccb->lun = scsi_dev_desc[device].lun; - buf_addr = (unsigned long)buffer; - start = blknr; - blks = blkcnt; - debug("\n%s: dev %d startblk " LBAF ", blccnt " LBAF " buffer %lx\n", - __func__, device, start, blks, (unsigned long)buffer); - do { - pccb->pdata = (unsigned char *)buf_addr; - if (blks > SCSI_MAX_WRITE_BLK) { - pccb->datalen = (scsi_dev_desc[device].blksz * - SCSI_MAX_WRITE_BLK); - smallblks = SCSI_MAX_WRITE_BLK; - scsi_setup_write_ext(pccb, start, smallblks); - start += SCSI_MAX_WRITE_BLK; - blks -= SCSI_MAX_WRITE_BLK; - } else { - pccb->datalen = scsi_dev_desc[device].blksz * blks; - smallblks = (unsigned short)blks; - scsi_setup_write_ext(pccb, start, smallblks); - start += blks; - blks = 0; - } - debug("%s: startblk " LBAF ", blccnt %x buffer %" PRIXPTR "\n", - __func__, start, smallblks, buf_addr); - if (scsi_exec(pccb) != true) { - scsi_print_error(pccb); - blkcnt -= blks; - break; - } - buf_addr += pccb->datalen; - } while (blks != 0); - debug("%s: end startblk " LBAF ", blccnt %x buffer %" PRIXPTR "\n", - __func__, start, smallblks, buf_addr); - return blkcnt; -} - /* copy src to dest, skipping leading and trailing blanks * and null terminate the string */ @@ -630,105 +607,106 @@ void scsi_setup_test_unit_ready(ccb * pccb) pccb->msgout[0]=SCSI_IDENTIFY; /* NOT USED */ } -#ifdef CONFIG_SYS_64BIT_LBA -void scsi_setup_read16(ccb * pccb, lbaint_t start, unsigned long blocks) +/********************************************************************************* + * (re)-scan the scsi bus and reports scsi device info + * to the user if mode = 1 + */ +void scsi_scan(int mode) { - pccb->cmd[0] = SCSI_READ16; - pccb->cmd[1] = pccb->lun<<5; - pccb->cmd[2] = ((unsigned char) (start >> 56)) & 0xff; - pccb->cmd[3] = ((unsigned char) (start >> 48)) & 0xff; - pccb->cmd[4] = ((unsigned char) (start >> 40)) & 0xff; - pccb->cmd[5] = ((unsigned char) (start >> 32)) & 0xff; - pccb->cmd[6] = ((unsigned char) (start >> 24)) & 0xff; - pccb->cmd[7] = ((unsigned char) (start >> 16)) & 0xff; - pccb->cmd[8] = ((unsigned char) (start >> 8)) & 0xff; - pccb->cmd[9] = ((unsigned char) (start)) & 0xff; - pccb->cmd[10] = 0; - pccb->cmd[11] = ((unsigned char) (blocks >> 24)) & 0xff; - pccb->cmd[12] = ((unsigned char) (blocks >> 16)) & 0xff; - pccb->cmd[13] = ((unsigned char) (blocks >> 8)) & 0xff; - pccb->cmd[14] = (unsigned char) blocks & 0xff; - pccb->cmd[15] = 0; - pccb->cmdlen = 16; - pccb->msgout[0] = SCSI_IDENTIFY; /* NOT USED */ - debug ("scsi_setup_read16: cmd: %02X %02X " - "startblk %02X%02X%02X%02X%02X%02X%02X%02X " - "blccnt %02X%02X%02X%02X\n", - pccb->cmd[0], pccb->cmd[1], - pccb->cmd[2], pccb->cmd[3], pccb->cmd[4], pccb->cmd[5], - pccb->cmd[6], pccb->cmd[7], pccb->cmd[8], pccb->cmd[9], - pccb->cmd[11], pccb->cmd[12], pccb->cmd[13], pccb->cmd[14]); -} -#endif + unsigned char i,perq,modi,lun; + lbaint_t capacity; + unsigned long blksz; + ccb* pccb=(ccb *)&tempccb; -void scsi_setup_read_ext(ccb * pccb, lbaint_t start, unsigned short blocks) -{ - pccb->cmd[0]=SCSI_READ10; - pccb->cmd[1]=pccb->lun<<5; - pccb->cmd[2]=((unsigned char) (start>>24))&0xff; - pccb->cmd[3]=((unsigned char) (start>>16))&0xff; - pccb->cmd[4]=((unsigned char) (start>>8))&0xff; - pccb->cmd[5]=((unsigned char) (start))&0xff; - pccb->cmd[6]=0; - pccb->cmd[7]=((unsigned char) (blocks>>8))&0xff; - pccb->cmd[8]=(unsigned char) blocks & 0xff; - pccb->cmd[6]=0; - pccb->cmdlen=10; - pccb->msgout[0]=SCSI_IDENTIFY; /* NOT USED */ - debug ("scsi_setup_read_ext: cmd: %02X %02X startblk %02X%02X%02X%02X blccnt %02X%02X\n", - pccb->cmd[0],pccb->cmd[1], - pccb->cmd[2],pccb->cmd[3],pccb->cmd[4],pccb->cmd[5], - pccb->cmd[7],pccb->cmd[8]); -} + if(mode==1) { + printf("scanning bus for devices...\n"); + } + for(i=0;itarget=i; + for(lun=0;lunlun=lun; + pccb->pdata=(unsigned char *)&tempbuff; + pccb->datalen=512; + scsi_setup_inquiry(pccb); + if (scsi_exec(pccb) != true) { + if(pccb->contr_stat==SCSI_SEL_TIME_OUT) { + debug ("Selection timeout ID %d\n",pccb->target); + continue; /* selection timeout => assuming no device present */ + } + scsi_print_error(pccb); + continue; + } + perq=tempbuff[0]; + modi=tempbuff[1]; + if((perq & 0x1f)==0x1f) { + continue; /* skip unknown devices */ + } + if((modi&0x80)==0x80) /* drive is removable */ + scsi_dev_desc[scsi_max_devs].removable=true; + /* get info for this device */ + scsi_ident_cpy((unsigned char *)&scsi_dev_desc[scsi_max_devs].vendor[0], + &tempbuff[8], 8); + scsi_ident_cpy((unsigned char *)&scsi_dev_desc[scsi_max_devs].product[0], + &tempbuff[16], 16); + scsi_ident_cpy((unsigned char *)&scsi_dev_desc[scsi_max_devs].revision[0], + &tempbuff[32], 4); + scsi_dev_desc[scsi_max_devs].target=pccb->target; + scsi_dev_desc[scsi_max_devs].lun=pccb->lun; -void scsi_setup_write_ext(ccb *pccb, lbaint_t start, unsigned short blocks) -{ - pccb->cmd[0] = SCSI_WRITE10; - pccb->cmd[1] = pccb->lun << 5; - pccb->cmd[2] = ((unsigned char) (start>>24)) & 0xff; - pccb->cmd[3] = ((unsigned char) (start>>16)) & 0xff; - pccb->cmd[4] = ((unsigned char) (start>>8)) & 0xff; - pccb->cmd[5] = ((unsigned char) (start)) & 0xff; - pccb->cmd[6] = 0; - pccb->cmd[7] = ((unsigned char) (blocks>>8)) & 0xff; - pccb->cmd[8] = (unsigned char)blocks & 0xff; - pccb->cmd[9] = 0; - pccb->cmdlen = 10; - pccb->msgout[0] = SCSI_IDENTIFY; /* NOT USED */ - debug("%s: cmd: %02X %02X startblk %02X%02X%02X%02X blccnt %02X%02X\n", - __func__, - pccb->cmd[0], pccb->cmd[1], - pccb->cmd[2], pccb->cmd[3], pccb->cmd[4], pccb->cmd[5], - pccb->cmd[7], pccb->cmd[8]); -} - -void scsi_setup_read6(ccb * pccb, lbaint_t start, unsigned short blocks) -{ - pccb->cmd[0]=SCSI_READ6; - pccb->cmd[1]=pccb->lun<<5 | (((unsigned char)(start>>16))&0x1f); - pccb->cmd[2]=((unsigned char) (start>>8))&0xff; - pccb->cmd[3]=((unsigned char) (start))&0xff; - pccb->cmd[4]=(unsigned char) blocks & 0xff; - pccb->cmd[5]=0; - pccb->cmdlen=6; - pccb->msgout[0]=SCSI_IDENTIFY; /* NOT USED */ - debug ("scsi_setup_read6: cmd: %02X %02X startblk %02X%02X blccnt %02X\n", - pccb->cmd[0],pccb->cmd[1], - pccb->cmd[2],pccb->cmd[3],pccb->cmd[4]); -} - - -void scsi_setup_inquiry(ccb * pccb) -{ - pccb->cmd[0]=SCSI_INQUIRY; - pccb->cmd[1]=pccb->lun<<5; - pccb->cmd[2]=0; - pccb->cmd[3]=0; - if(pccb->datalen>255) - pccb->cmd[4]=255; + pccb->datalen=0; + scsi_setup_test_unit_ready(pccb); + if (scsi_exec(pccb) != true) { + if (scsi_dev_desc[scsi_max_devs].removable == true) { + scsi_dev_desc[scsi_max_devs].type=perq; + goto removable; + } + scsi_print_error(pccb); + continue; + } + if (scsi_read_capacity(pccb, &capacity, &blksz)) { + scsi_print_error(pccb); + continue; + } + scsi_dev_desc[scsi_max_devs].lba=capacity; + scsi_dev_desc[scsi_max_devs].blksz=blksz; + scsi_dev_desc[scsi_max_devs].log2blksz = + LOG2(scsi_dev_desc[scsi_max_devs].blksz); + scsi_dev_desc[scsi_max_devs].type=perq; + part_init(&scsi_dev_desc[scsi_max_devs]); +removable: + if(mode==1) { + printf (" Device %d: ", scsi_max_devs); + dev_print(&scsi_dev_desc[scsi_max_devs]); + } /* if mode */ + scsi_max_devs++; + } /* next LUN */ + } + if(scsi_max_devs>0) + scsi_curr_dev=0; else - pccb->cmd[4]=(unsigned char)pccb->datalen; - pccb->cmd[5]=0; - pccb->cmdlen=6; - pccb->msgout[0]=SCSI_IDENTIFY; /* NOT USED */ + scsi_curr_dev = -1; + + printf("Found %d device(s).\n", scsi_max_devs); +#ifndef CONFIG_SPL_BUILD + setenv_ulong("scsidevs", scsi_max_devs); +#endif } From f1d4d9379e1f83118307012a3edcc4ea20e12d92 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 1 May 2016 11:35:58 -0600 Subject: [PATCH 046/162] dm: scsi: Fix up code style Update the code style of this file so that it passes checkpatch.pl. Signed-off-by: Simon Glass --- cmd/scsi.c | 459 ++++++++++++++++++++++++++--------------------------- 1 file changed, 226 insertions(+), 233 deletions(-) diff --git a/cmd/scsi.c b/cmd/scsi.c index 9ba070f8b9..751fc5818a 100644 --- a/cmd/scsi.c +++ b/cmd/scsi.c @@ -50,59 +50,53 @@ static int scsi_curr_dev; /* current device */ static struct blk_desc scsi_dev_desc[CONFIG_SYS_SCSI_MAX_DEVICE]; -/**************************************************************************************** - * scsi_read - */ - /* almost the maximum amount of the scsi_ext command.. */ #define SCSI_MAX_READ_BLK 0xFFFF #define SCSI_LBA48_READ 0xFFFFFFF #ifdef CONFIG_SYS_64BIT_LBA -void scsi_setup_read16(ccb * pccb, lbaint_t start, unsigned long blocks) +void scsi_setup_read16(ccb *pccb, lbaint_t start, unsigned long blocks) { pccb->cmd[0] = SCSI_READ16; - pccb->cmd[1] = pccb->lun<<5; - pccb->cmd[2] = ((unsigned char) (start >> 56)) & 0xff; - pccb->cmd[3] = ((unsigned char) (start >> 48)) & 0xff; - pccb->cmd[4] = ((unsigned char) (start >> 40)) & 0xff; - pccb->cmd[5] = ((unsigned char) (start >> 32)) & 0xff; - pccb->cmd[6] = ((unsigned char) (start >> 24)) & 0xff; - pccb->cmd[7] = ((unsigned char) (start >> 16)) & 0xff; - pccb->cmd[8] = ((unsigned char) (start >> 8)) & 0xff; - pccb->cmd[9] = ((unsigned char) (start)) & 0xff; + pccb->cmd[1] = pccb->lun << 5; + pccb->cmd[2] = (unsigned char)(start >> 56) & 0xff; + pccb->cmd[3] = (unsigned char)(start >> 48) & 0xff; + pccb->cmd[4] = (unsigned char)(start >> 40) & 0xff; + pccb->cmd[5] = (unsigned char)(start >> 32) & 0xff; + pccb->cmd[6] = (unsigned char)(start >> 24) & 0xff; + pccb->cmd[7] = (unsigned char)(start >> 16) & 0xff; + pccb->cmd[8] = (unsigned char)(start >> 8) & 0xff; + pccb->cmd[9] = (unsigned char)start & 0xff; pccb->cmd[10] = 0; - pccb->cmd[11] = ((unsigned char) (blocks >> 24)) & 0xff; - pccb->cmd[12] = ((unsigned char) (blocks >> 16)) & 0xff; - pccb->cmd[13] = ((unsigned char) (blocks >> 8)) & 0xff; - pccb->cmd[14] = (unsigned char) blocks & 0xff; + pccb->cmd[11] = (unsigned char)(blocks >> 24) & 0xff; + pccb->cmd[12] = (unsigned char)(blocks >> 16) & 0xff; + pccb->cmd[13] = (unsigned char)(blocks >> 8) & 0xff; + pccb->cmd[14] = (unsigned char)blocks & 0xff; pccb->cmd[15] = 0; pccb->cmdlen = 16; pccb->msgout[0] = SCSI_IDENTIFY; /* NOT USED */ - debug ("scsi_setup_read16: cmd: %02X %02X " - "startblk %02X%02X%02X%02X%02X%02X%02X%02X " - "blccnt %02X%02X%02X%02X\n", - pccb->cmd[0], pccb->cmd[1], - pccb->cmd[2], pccb->cmd[3], pccb->cmd[4], pccb->cmd[5], - pccb->cmd[6], pccb->cmd[7], pccb->cmd[8], pccb->cmd[9], - pccb->cmd[11], pccb->cmd[12], pccb->cmd[13], pccb->cmd[14]); + debug("scsi_setup_read16: cmd: %02X %02X startblk %02X%02X%02X%02X%02X%02X%02X%02X blccnt %02X%02X%02X%02X\n", + pccb->cmd[0], pccb->cmd[1], + pccb->cmd[2], pccb->cmd[3], pccb->cmd[4], pccb->cmd[5], + pccb->cmd[6], pccb->cmd[7], pccb->cmd[8], pccb->cmd[9], + pccb->cmd[11], pccb->cmd[12], pccb->cmd[13], pccb->cmd[14]); } #endif void scsi_setup_read_ext(ccb * pccb, lbaint_t start, unsigned short blocks) { - pccb->cmd[0]=SCSI_READ10; - pccb->cmd[1]=pccb->lun<<5; - pccb->cmd[2]=((unsigned char) (start>>24))&0xff; - pccb->cmd[3]=((unsigned char) (start>>16))&0xff; - pccb->cmd[4]=((unsigned char) (start>>8))&0xff; - pccb->cmd[5]=((unsigned char) (start))&0xff; - pccb->cmd[6]=0; - pccb->cmd[7]=((unsigned char) (blocks>>8))&0xff; - pccb->cmd[8]=(unsigned char) blocks & 0xff; - pccb->cmd[6]=0; + pccb->cmd[0] = SCSI_READ10; + pccb->cmd[1] = pccb->lun << 5; + pccb->cmd[2] = (unsigned char)(start >> 24) & 0xff; + pccb->cmd[3] = (unsigned char)(start >> 16) & 0xff; + pccb->cmd[4] = (unsigned char)(start >> 8) & 0xff; + pccb->cmd[5] = (unsigned char)start & 0xff; + pccb->cmd[6] = 0; + pccb->cmd[7] = (unsigned char)(blocks >> 8) & 0xff; + pccb->cmd[8] = (unsigned char)blocks & 0xff; + pccb->cmd[6] = 0; pccb->cmdlen=10; - pccb->msgout[0]=SCSI_IDENTIFY; /* NOT USED */ + pccb->msgout[0] = SCSI_IDENTIFY; /* NOT USED */ debug ("scsi_setup_read_ext: cmd: %02X %02X startblk %02X%02X%02X%02X blccnt %02X%02X\n", pccb->cmd[0],pccb->cmd[1], pccb->cmd[2],pccb->cmd[3],pccb->cmd[4],pccb->cmd[5], @@ -113,12 +107,12 @@ void scsi_setup_write_ext(ccb *pccb, lbaint_t start, unsigned short blocks) { pccb->cmd[0] = SCSI_WRITE10; pccb->cmd[1] = pccb->lun << 5; - pccb->cmd[2] = ((unsigned char) (start>>24)) & 0xff; - pccb->cmd[3] = ((unsigned char) (start>>16)) & 0xff; - pccb->cmd[4] = ((unsigned char) (start>>8)) & 0xff; - pccb->cmd[5] = ((unsigned char) (start)) & 0xff; + pccb->cmd[2] = (unsigned char)(start >> 24) & 0xff; + pccb->cmd[3] = (unsigned char)(start >> 16) & 0xff; + pccb->cmd[4] = (unsigned char)(start >> 8) & 0xff; + pccb->cmd[5] = (unsigned char)start & 0xff; pccb->cmd[6] = 0; - pccb->cmd[7] = ((unsigned char) (blocks>>8)) & 0xff; + pccb->cmd[7] = ((unsigned char)(blocks >> 8)) & 0xff; pccb->cmd[8] = (unsigned char)blocks & 0xff; pccb->cmd[9] = 0; pccb->cmdlen = 10; @@ -132,33 +126,33 @@ void scsi_setup_write_ext(ccb *pccb, lbaint_t start, unsigned short blocks) void scsi_setup_read6(ccb * pccb, lbaint_t start, unsigned short blocks) { - pccb->cmd[0]=SCSI_READ6; - pccb->cmd[1]=pccb->lun<<5 | (((unsigned char)(start>>16))&0x1f); - pccb->cmd[2]=((unsigned char) (start>>8))&0xff; - pccb->cmd[3]=((unsigned char) (start))&0xff; - pccb->cmd[4]=(unsigned char) blocks & 0xff; - pccb->cmd[5]=0; + pccb->cmd[0] = SCSI_READ6; + pccb->cmd[1] = pccb->lun << 5 | ((unsigned char)(start >> 16) & 0x1f); + pccb->cmd[2] = (unsigned char)(start >> 8) & 0xff; + pccb->cmd[3] = (unsigned char)start & 0xff; + pccb->cmd[4] = (unsigned char)blocks & 0xff; + pccb->cmd[5] = 0; pccb->cmdlen=6; - pccb->msgout[0]=SCSI_IDENTIFY; /* NOT USED */ - debug ("scsi_setup_read6: cmd: %02X %02X startblk %02X%02X blccnt %02X\n", - pccb->cmd[0],pccb->cmd[1], - pccb->cmd[2],pccb->cmd[3],pccb->cmd[4]); + pccb->msgout[0] = SCSI_IDENTIFY; /* NOT USED */ + debug("scsi_setup_read6: cmd: %02X %02X startblk %02X%02X blccnt %02X\n", + pccb->cmd[0], pccb->cmd[1], + pccb->cmd[2], pccb->cmd[3], pccb->cmd[4]); } void scsi_setup_inquiry(ccb * pccb) { - pccb->cmd[0]=SCSI_INQUIRY; - pccb->cmd[1]=pccb->lun<<5; - pccb->cmd[2]=0; - pccb->cmd[3]=0; - if(pccb->datalen>255) - pccb->cmd[4]=255; + pccb->cmd[0] = SCSI_INQUIRY; + pccb->cmd[1] = pccb->lun << 5; + pccb->cmd[2] = 0; + pccb->cmd[3] = 0; + if (pccb->datalen > 255) + pccb->cmd[4] = 255; else - pccb->cmd[4]=(unsigned char)pccb->datalen; - pccb->cmd[5]=0; + pccb->cmd[4] = (unsigned char)pccb->datalen; + pccb->cmd[5] = 0; pccb->cmdlen=6; - pccb->msgout[0]=SCSI_IDENTIFY; /* NOT USED */ + pccb->msgout[0] = SCSI_IDENTIFY; /* NOT USED */ } static ulong scsi_read(struct blk_desc *block_dev, lbaint_t blknr, @@ -170,18 +164,18 @@ static ulong scsi_read(struct blk_desc *block_dev, lbaint_t blknr, unsigned short smallblks = 0; ccb* pccb=(ccb *)&tempccb; device&=0xff; - /* Setup device - */ - pccb->target=scsi_dev_desc[device].target; - pccb->lun=scsi_dev_desc[device].lun; - buf_addr=(unsigned long)buffer; - start=blknr; - blks=blkcnt; + + /* Setup device */ + pccb->target = scsi_dev_desc[device].target; + pccb->lun = scsi_dev_desc[device].lun; + buf_addr = (unsigned long)buffer; + start = blknr; + blks = blkcnt; debug("\nscsi_read: dev %d startblk " LBAF ", blccnt " LBAF " buffer %lx\n", device, start, blks, (unsigned long)buffer); do { - pccb->pdata=(unsigned char *)buf_addr; + pccb->pdata = (unsigned char *)buf_addr; #ifdef CONFIG_SYS_64BIT_LBA if (start > SCSI_LBA48_READ) { unsigned long blocks; @@ -193,17 +187,18 @@ static ulong scsi_read(struct blk_desc *block_dev, lbaint_t blknr, } else #endif if (blks > SCSI_MAX_READ_BLK) { - pccb->datalen=scsi_dev_desc[device].blksz * SCSI_MAX_READ_BLK; - smallblks=SCSI_MAX_READ_BLK; - scsi_setup_read_ext(pccb,start,smallblks); - start+=SCSI_MAX_READ_BLK; - blks-=SCSI_MAX_READ_BLK; + pccb->datalen = scsi_dev_desc[device].blksz * + SCSI_MAX_READ_BLK; + smallblks = SCSI_MAX_READ_BLK; + scsi_setup_read_ext(pccb, start, smallblks); + start += SCSI_MAX_READ_BLK; + blks -= SCSI_MAX_READ_BLK; } else { - pccb->datalen=scsi_dev_desc[device].blksz * blks; - smallblks=(unsigned short) blks; - scsi_setup_read_ext(pccb,start,smallblks); - start+=blks; + pccb->datalen = scsi_dev_desc[device].blksz * blks; + smallblks = (unsigned short)blks; + scsi_setup_read_ext(pccb, start, smallblks); + start += blks; blks=0; } debug("scsi_read_ext: startblk " LBAF @@ -211,14 +206,14 @@ static ulong scsi_read(struct blk_desc *block_dev, lbaint_t blknr, start, smallblks, buf_addr); if (scsi_exec(pccb) != true) { scsi_print_error(pccb); - blkcnt-=blks; + blkcnt -= blks; break; } buf_addr+=pccb->datalen; - } while(blks!=0); + } while (blks != 0); debug("scsi_read_ext: end startblk " LBAF ", blccnt %x buffer %" PRIXPTR "\n", start, smallblks, buf_addr); - return(blkcnt); + return blkcnt; } /******************************************************************************* @@ -365,106 +360,106 @@ int do_scsi (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) return CMD_RET_USAGE; case 2: - if (strncmp(argv[1],"res",3) == 0) { - printf("\nReset SCSI\n"); - scsi_bus_reset(); - scsi_scan(1); - return 0; + if (strncmp(argv[1], "res", 3) == 0) { + printf("\nReset SCSI\n"); + scsi_bus_reset(); + scsi_scan(1); + return 0; + } + if (strncmp(argv[1], "inf", 3) == 0) { + int i; + for (i = 0; i < CONFIG_SYS_SCSI_MAX_DEVICE; ++i) { + if (scsi_dev_desc[i].type == DEV_TYPE_UNKNOWN) + continue; /* list only known devices */ + printf("SCSI dev. %d: ", i); + dev_print(&scsi_dev_desc[i]); } - if (strncmp(argv[1],"inf",3) == 0) { - int i; - for (i=0; i= CONFIG_SYS_SCSI_MAX_DEVICE)) { - printf("\nno SCSI devices available\n"); - return 1; - } - printf ("\n Device %d: ", scsi_curr_dev); - dev_print(&scsi_dev_desc[scsi_curr_dev]); - return 0; - } - if (strncmp(argv[1],"scan",4) == 0) { - scsi_scan(1); - return 0; - } - if (strncmp(argv[1],"part",4) == 0) { - int dev, ok; - for (ok=0, dev=0; dev= CONFIG_SYS_SCSI_MAX_DEVICE) { + printf("\nno SCSI devices available\n"); return 1; } - return CMD_RET_USAGE; - case 3: - if (strncmp(argv[1],"dev",3) == 0) { - int dev = (int)simple_strtoul(argv[2], NULL, 10); - printf ("\nSCSI device %d: ", dev); - if (dev >= CONFIG_SYS_SCSI_MAX_DEVICE) { - printf("unknown device\n"); - return 1; - } - printf ("\n Device %d: ", dev); - dev_print(&scsi_dev_desc[dev]); - if(scsi_dev_desc[dev].type == DEV_TYPE_UNKNOWN) { - return 1; - } - scsi_curr_dev = dev; - printf("... is now current device\n"); - return 0; - } - if (strncmp(argv[1],"part",4) == 0) { - int dev = (int)simple_strtoul(argv[2], NULL, 10); - if(scsi_dev_desc[dev].type != DEV_TYPE_UNKNOWN) { + printf("\n Device %d: ", scsi_curr_dev); + dev_print(&scsi_dev_desc[scsi_curr_dev]); + return 0; + } + if (strncmp(argv[1], "scan", 4) == 0) { + scsi_scan(1); + return 0; + } + if (strncmp(argv[1], "part", 4) == 0) { + int dev, ok; + for (ok = 0, dev = 0; + dev < CONFIG_SYS_SCSI_MAX_DEVICE; ++dev) { + if (scsi_dev_desc[dev].type != + DEV_TYPE_UNKNOWN) { + ok++; + if (dev) + printf("\n"); + debug("print_part of %x\n", dev); part_print(&scsi_dev_desc[dev]); } - else { - printf ("\nSCSI device %d not available\n", dev); - } + } + if (!ok) + printf("\nno SCSI devices available\n"); + return 1; + } + return CMD_RET_USAGE; + case 3: + if (strncmp(argv[1], "dev", 3) == 0) { + int dev = (int)simple_strtoul(argv[2], NULL, 10); + printf("\nSCSI device %d: ", dev); + if (dev >= CONFIG_SYS_SCSI_MAX_DEVICE) { + printf("unknown device\n"); return 1; } - return CMD_RET_USAGE; - default: - /* at least 4 args */ - if (strcmp(argv[1],"read") == 0) { - ulong addr = simple_strtoul(argv[2], NULL, 16); - ulong blk = simple_strtoul(argv[3], NULL, 16); - ulong cnt = simple_strtoul(argv[4], NULL, 16); - ulong n; - printf ("\nSCSI read: device %d block # %ld, count %ld ... ", - scsi_curr_dev, blk, cnt); - n = scsi_read(&scsi_dev_desc[scsi_curr_dev], - blk, cnt, (ulong *)addr); - printf ("%ld blocks read: %s\n",n,(n==cnt) ? "OK" : "ERROR"); - return 0; - } else if (strcmp(argv[1], "write") == 0) { - ulong addr = simple_strtoul(argv[2], NULL, 16); - ulong blk = simple_strtoul(argv[3], NULL, 16); - ulong cnt = simple_strtoul(argv[4], NULL, 16); - ulong n; - printf("\nSCSI write: device %d block # %ld, " - "count %ld ... ", - scsi_curr_dev, blk, cnt); - n = scsi_write(&scsi_dev_desc[scsi_curr_dev], - blk, cnt, (ulong *)addr); - printf("%ld blocks written: %s\n", n, - (n == cnt) ? "OK" : "ERROR"); - return 0; - } + printf("\n Device %d: ", dev); + dev_print(&scsi_dev_desc[dev]); + if (scsi_dev_desc[dev].type == DEV_TYPE_UNKNOWN) + return 1; + scsi_curr_dev = dev; + printf("... is now current device\n"); + return 0; + } + if (strncmp(argv[1], "part", 4) == 0) { + int dev = (int)simple_strtoul(argv[2], NULL, 10); + if (scsi_dev_desc[dev].type != DEV_TYPE_UNKNOWN) + part_print(&scsi_dev_desc[dev]); + else + printf("\nSCSI device %d not available\n", dev); + return 1; + } + return CMD_RET_USAGE; + default: + /* at least 4 args */ + if (strcmp(argv[1], "read") == 0) { + ulong addr = simple_strtoul(argv[2], NULL, 16); + ulong blk = simple_strtoul(argv[3], NULL, 16); + ulong cnt = simple_strtoul(argv[4], NULL, 16); + ulong n; + printf("\nSCSI read: device %d block # %ld, count %ld ... ", + scsi_curr_dev, blk, cnt); + n = scsi_read(&scsi_dev_desc[scsi_curr_dev], + blk, cnt, (ulong *)addr); + printf("%ld blocks read: %s\n", n, + n == cnt ? "OK" : "ERROR"); + return 0; + } else if (strcmp(argv[1], "write") == 0) { + ulong addr = simple_strtoul(argv[2], NULL, 16); + ulong blk = simple_strtoul(argv[3], NULL, 16); + ulong cnt = simple_strtoul(argv[4], NULL, 16); + ulong n; + printf("\nSCSI write: device %d block # %ld, count %ld ... ", + scsi_curr_dev, blk, cnt); + n = scsi_write(&scsi_dev_desc[scsi_curr_dev], + blk, cnt, (ulong *)addr); + printf("%ld blocks written: %s\n", n, + n == cnt ? "OK" : "ERROR"); + return 0; + } } /* switch */ return CMD_RET_USAGE; } @@ -493,25 +488,24 @@ U_BOOT_CMD( /* copy src to dest, skipping leading and trailing blanks * and null terminate the string */ -void scsi_ident_cpy (unsigned char *dest, unsigned char *src, unsigned int len) +void scsi_ident_cpy(unsigned char *dest, unsigned char *src, unsigned int len) { int start,end; - start=0; - while(startstart) { - if(src[end]!=' ') + end = len-1; + while (end > start) { + if (src[end] != ' ') break; end--; } - for( ; start<=end; start++) { - *dest++=src[start]; - } + for (; start <= end; start++) + *dest ++= src[start]; *dest='\0'; } @@ -534,7 +528,7 @@ int scsi_read_capacity(ccb *pccb, lbaint_t *capacity, unsigned long *blksz) { *capacity = 0; - memset(pccb->cmd, 0, sizeof(pccb->cmd)); + memset(pccb->cmd, '\0', sizeof(pccb->cmd)); pccb->cmd[0] = SCSI_RD_CAPAC10; pccb->cmd[1] = pccb->lun << 5; pccb->cmdlen = 10; @@ -559,8 +553,7 @@ int scsi_read_capacity(ccb *pccb, lbaint_t *capacity, unsigned long *blksz) } /* Read capacity (10) was insufficient. Use read capacity (16). */ - - memset(pccb->cmd, 0, sizeof(pccb->cmd)); + memset(pccb->cmd, '\0', sizeof(pccb->cmd)); pccb->cmd[0] = SCSI_RD_CAPAC16; pccb->cmd[1] = 0x10; pccb->cmdlen = 16; @@ -597,14 +590,14 @@ int scsi_read_capacity(ccb *pccb, lbaint_t *capacity, unsigned long *blksz) */ void scsi_setup_test_unit_ready(ccb * pccb) { - pccb->cmd[0]=SCSI_TST_U_RDY; - pccb->cmd[1]=pccb->lun<<5; - pccb->cmd[2]=0; - pccb->cmd[3]=0; - pccb->cmd[4]=0; - pccb->cmd[5]=0; - pccb->cmdlen=6; - pccb->msgout[0]=SCSI_IDENTIFY; /* NOT USED */ + pccb->cmd[0] = SCSI_TST_U_RDY; + pccb->cmd[1] = pccb->lun << 5; + pccb->cmd[2] = 0; + pccb->cmd[3] = 0; + pccb->cmd[4] = 0; + pccb->cmd[5] = 0; + pccb->cmdlen = 6; + pccb->msgout[0] = SCSI_IDENTIFY; /* NOT USED */ } /********************************************************************************* @@ -618,50 +611,49 @@ void scsi_scan(int mode) unsigned long blksz; ccb* pccb=(ccb *)&tempccb; - if(mode==1) { + if (mode == 1) printf("scanning bus for devices...\n"); - } - for(i=0;itarget=i; - for(lun=0;lunlun=lun; - pccb->pdata=(unsigned char *)&tempbuff; - pccb->datalen=512; + scsi_max_devs = 0; + for (i = 0; i < CONFIG_SYS_SCSI_MAX_SCSI_ID; i++) { + pccb->target = i; + for (lun = 0; lun < CONFIG_SYS_SCSI_MAX_LUN; lun++) { + pccb->lun = lun; + pccb->pdata = (unsigned char *)&tempbuff; + pccb->datalen = 512; scsi_setup_inquiry(pccb); if (scsi_exec(pccb) != true) { if(pccb->contr_stat==SCSI_SEL_TIME_OUT) { - debug ("Selection timeout ID %d\n",pccb->target); + debug("Selection timeout ID %d\n", + pccb->target); continue; /* selection timeout => assuming no device present */ } scsi_print_error(pccb); continue; } - perq=tempbuff[0]; - modi=tempbuff[1]; - if((perq & 0x1f)==0x1f) { + perq = tempbuff[0]; + modi = tempbuff[1]; + if ((perq & 0x1f) == 0x1f) continue; /* skip unknown devices */ - } - if((modi&0x80)==0x80) /* drive is removable */ - scsi_dev_desc[scsi_max_devs].removable=true; + if ((modi & 0x80) == 0x80) /* drive is removable */ + scsi_dev_desc[scsi_max_devs].removable = true; /* get info for this device */ scsi_ident_cpy((unsigned char *)&scsi_dev_desc[scsi_max_devs].vendor[0], &tempbuff[8], 8); @@ -669,14 +661,15 @@ void scsi_scan(int mode) &tempbuff[16], 16); scsi_ident_cpy((unsigned char *)&scsi_dev_desc[scsi_max_devs].revision[0], &tempbuff[32], 4); - scsi_dev_desc[scsi_max_devs].target=pccb->target; - scsi_dev_desc[scsi_max_devs].lun=pccb->lun; + scsi_dev_desc[scsi_max_devs].target = pccb->target; + scsi_dev_desc[scsi_max_devs].lun = pccb->lun; - pccb->datalen=0; + pccb->datalen = 0; scsi_setup_test_unit_ready(pccb); if (scsi_exec(pccb) != true) { - if (scsi_dev_desc[scsi_max_devs].removable == true) { - scsi_dev_desc[scsi_max_devs].type=perq; + if (scsi_dev_desc[scsi_max_devs].removable) { + scsi_dev_desc[scsi_max_devs].type = + perq; goto removable; } scsi_print_error(pccb); @@ -686,11 +679,11 @@ void scsi_scan(int mode) scsi_print_error(pccb); continue; } - scsi_dev_desc[scsi_max_devs].lba=capacity; - scsi_dev_desc[scsi_max_devs].blksz=blksz; + scsi_dev_desc[scsi_max_devs].lba = capacity; + scsi_dev_desc[scsi_max_devs].blksz = blksz; scsi_dev_desc[scsi_max_devs].log2blksz = LOG2(scsi_dev_desc[scsi_max_devs].blksz); - scsi_dev_desc[scsi_max_devs].type=perq; + scsi_dev_desc[scsi_max_devs].type = perq; part_init(&scsi_dev_desc[scsi_max_devs]); removable: if(mode==1) { @@ -700,8 +693,8 @@ removable: scsi_max_devs++; } /* next LUN */ } - if(scsi_max_devs>0) - scsi_curr_dev=0; + if (scsi_max_devs > 0) + scsi_curr_dev = 0; else scsi_curr_dev = -1; From 53dbcdd0cd4b90077b0b3893bcf25354ed825cec Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 1 May 2016 11:35:59 -0600 Subject: [PATCH 047/162] dm: ide: Correct various code style problems Adjust common/ide.c so that it passes most checkpatch.pl checks. Signed-off-by: Simon Glass --- cmd/ide.c | 57 ++++++++++++++++++++++++++++--------------------------- 1 file changed, 29 insertions(+), 28 deletions(-) diff --git a/cmd/ide.c b/cmd/ide.c index c4c08c8855..a46d0acfd6 100644 --- a/cmd/ide.c +++ b/cmd/ide.c @@ -58,13 +58,13 @@ struct blk_desc ide_dev_desc[CONFIG_SYS_IDE_MAXDEVICE]; /* ------------------------------------------------------------------------- */ #ifdef CONFIG_IDE_RESET -static void ide_reset (void); +static void ide_reset(void); #else #define ide_reset() /* dummy */ #endif static void ide_ident(struct blk_desc *dev_desc); -static uchar ide_wait (int dev, ulong t); +static uchar ide_wait(int dev, ulong t); #define IDE_TIME_OUT 2000 /* 2 sec timeout */ @@ -72,14 +72,15 @@ static uchar ide_wait (int dev, ulong t); #define IDE_SPIN_UP_TIME_OUT 5000 /* 5 sec spin-up timeout */ -static void ident_cpy (unsigned char *dest, unsigned char *src, unsigned int len); +static void ident_cpy(unsigned char *dest, unsigned char *src, + unsigned int len); #ifndef CONFIG_SYS_ATA_PORT_ADDR #define CONFIG_SYS_ATA_PORT_ADDR(port) (port) #endif #ifdef CONFIG_ATAPI -static void atapi_inquiry(struct blk_desc *dev_desc); +static void atapi_inquiry(struct blk_desc *dev_desc); static ulong atapi_read(struct blk_desc *block_dev, lbaint_t blknr, lbaint_t blkcnt, void *buffer); #endif @@ -150,7 +151,7 @@ int do_ide(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) return CMD_RET_USAGE; case 3: if (strncmp(argv[1], "dev", 3) == 0) { - int dev = (int) simple_strtoul(argv[2], NULL, 10); + int dev = (int)simple_strtoul(argv[2], NULL, 10); printf("\nIDE device %d: ", dev); if (dev >= CONFIG_SYS_IDE_MAXDEVICE) { @@ -169,7 +170,7 @@ int do_ide(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) return 0; } else if (strncmp(argv[1], "part", 4) == 0) { - int dev = (int) simple_strtoul(argv[2], NULL, 10); + int dev = (int)simple_strtoul(argv[2], NULL, 10); if (ide_dev_desc[dev].part_type != PART_TYPE_UNKNOWN) { part_print(&ide_dev_desc[dev]); @@ -194,13 +195,13 @@ int do_ide(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) #ifdef CONFIG_SYS_64BIT_LBA lbaint_t blk = simple_strtoull(argv[3], NULL, 16); - printf("\nIDE read: device %d block # %lld, count %ld ... ", - curr_device, blk, cnt); + printf("\nIDE read: device %d block # %lld, count %ld...", + curr_device, blk, cnt); #else lbaint_t blk = simple_strtoul(argv[3], NULL, 16); - printf("\nIDE read: device %d block # %ld, count %ld ... ", - curr_device, blk, cnt); + printf("\nIDE read: device %d block # %ld, count %ld...", + curr_device, blk, cnt); #endif dev_desc = &ide_dev_desc[curr_device]; @@ -223,13 +224,13 @@ int do_ide(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) #ifdef CONFIG_SYS_64BIT_LBA lbaint_t blk = simple_strtoull(argv[3], NULL, 16); - printf("\nIDE write: device %d block # %lld, count %ld ... ", - curr_device, blk, cnt); + printf("\nIDE write: device %d block # %lld, count %ld...", + curr_device, blk, cnt); #else lbaint_t blk = simple_strtoul(argv[3], NULL, 16); - printf("\nIDE write: device %d block # %ld, count %ld ... ", - curr_device, blk, cnt); + printf("\nIDE write: device %d block # %ld, count %ld...", + curr_device, blk, cnt); #endif n = ide_write(&ide_dev_desc[curr_device], blk, cnt, (ulong *)addr); @@ -833,7 +834,7 @@ ulong ide_read(struct blk_desc *block_dev, lbaint_t blknr, lbaint_t blkcnt, } IDE_READ_E: ide_led(DEVICE_LED(device), 0); /* LED off */ - return (n); + return n; } /* ------------------------------------------------------------------------- */ @@ -922,7 +923,7 @@ ulong ide_write(struct blk_desc *block_dev, lbaint_t blknr, lbaint_t blkcnt, } WR_OUT: ide_led(DEVICE_LED(device), 0); /* LED off */ - return (n); + return n; } /* ------------------------------------------------------------------------- */ @@ -974,7 +975,7 @@ static uchar ide_wait(int dev, ulong t) if (delay-- == 0) break; } - return (c); + return c; } /* ------------------------------------------------------------------------- */ @@ -1098,7 +1099,7 @@ static uchar atapi_wait_mask(int dev, ulong t, uchar mask, uchar res) if (delay-- == 0) break; } - return (c); + return c; } /* @@ -1142,7 +1143,7 @@ unsigned char atapi_issue(int device, unsigned char *ccb, int ccblen, if ((c & mask) != res) { /* DRQ must be 1, BSY 0 */ printf("ATAPI_ISSUE: Error (no IRQ) before sending ccb dev %d status 0x%02x\n", - device, c); + device, c); err = 0xFF; goto AI_OUT; } @@ -1166,10 +1167,10 @@ unsigned char atapi_issue(int device, unsigned char *ccb, int ccblen, if (c & ATA_STAT_ERR) { err = (ide_inb(device, ATA_ERROR_REG)) >> 4; debug("atapi_issue 1 returned sense key %X status %02X\n", - err, c); + err, c); } else { printf("ATAPI_ISSUE: (no DRQ) after sending ccb (%x) status 0x%02x\n", - ccb[0], c); + ccb[0], c); err = 0xFF; } goto AI_OUT; @@ -1190,7 +1191,7 @@ unsigned char atapi_issue(int device, unsigned char *ccb, int ccblen, } if (n != buflen) { debug("WARNING, transfer bytes %d not equal with requested %d\n", - n, buflen); + n, buflen); } if (n != 0) { /* data transfer */ debug("ATAPI_ISSUE: %d Bytes to transfer\n", n); @@ -1220,7 +1221,7 @@ unsigned char atapi_issue(int device, unsigned char *ccb, int ccblen, } AI_OUT: ide_led(DEVICE_LED(device), 0); /* LED off */ - return (err); + return err; } /* @@ -1297,7 +1298,7 @@ retry: ascq); error: debug("ERROR Sense key %02X ASC %02X ASCQ %02X\n", key, asc, ascq); - return (0xFF); + return 0xFF; } @@ -1402,8 +1403,8 @@ ulong atapi_read(struct blk_desc *block_dev, lbaint_t blknr, lbaint_t blkcnt, unsigned char ccb[12]; /* Command descriptor block */ ulong cnt; - debug("atapi_read dev %d start " LBAF " blocks " LBAF " buffer at %lX\n", - device, blknr, blkcnt, (ulong) buffer); + debug("atapi_read dev %d start " LBAF " blocks " LBAF + " buffer at %lX\n", device, blknr, blkcnt, (ulong) buffer); do { if (blkcnt > ATAPI_READ_MAX_BLOCK) @@ -1428,14 +1429,14 @@ ulong atapi_read(struct blk_desc *block_dev, lbaint_t blknr, lbaint_t blkcnt, (unsigned char *) buffer, cnt * ATAPI_READ_BLOCK_SIZE) == 0xFF) { - return (n); + return n; } n += cnt; blkcnt -= cnt; blknr += cnt; buffer += (cnt * ATAPI_READ_BLOCK_SIZE); } while (blkcnt > 0); - return (n); + return n; } /* ------------------------------------------------------------------------- */ From ed73508dec40afee7c90048fac510796bf91314d Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 1 May 2016 11:36:00 -0600 Subject: [PATCH 048/162] dm: ide: Remove the forward declarations Reorder the code to avoid needing forward declarations. Fix up code style as needed. Signed-off-by: Simon Glass --- cmd/ide.c | 1402 ++++++++++++++++++++++++++--------------------------- 1 file changed, 685 insertions(+), 717 deletions(-) diff --git a/cmd/ide.c b/cmd/ide.c index a46d0acfd6..db26f4320d 100644 --- a/cmd/ide.c +++ b/cmd/ide.c @@ -57,34 +57,686 @@ static int ide_bus_ok[CONFIG_SYS_IDE_MAXBUS]; struct blk_desc ide_dev_desc[CONFIG_SYS_IDE_MAXDEVICE]; /* ------------------------------------------------------------------------- */ -#ifdef CONFIG_IDE_RESET -static void ide_reset(void); -#else -#define ide_reset() /* dummy */ -#endif - -static void ide_ident(struct blk_desc *dev_desc); -static uchar ide_wait(int dev, ulong t); - #define IDE_TIME_OUT 2000 /* 2 sec timeout */ #define ATAPI_TIME_OUT 7000 /* 7 sec timeout (5 sec seems to work...) */ #define IDE_SPIN_UP_TIME_OUT 5000 /* 5 sec spin-up timeout */ -static void ident_cpy(unsigned char *dest, unsigned char *src, - unsigned int len); - #ifndef CONFIG_SYS_ATA_PORT_ADDR #define CONFIG_SYS_ATA_PORT_ADDR(port) (port) #endif -#ifdef CONFIG_ATAPI -static void atapi_inquiry(struct blk_desc *dev_desc); -static ulong atapi_read(struct blk_desc *block_dev, lbaint_t blknr, - lbaint_t blkcnt, void *buffer); +#ifndef CONFIG_IDE_LED /* define LED macros, they are not used anyways */ +# define DEVICE_LED(x) 0 +# define LED_IDE1 1 +# define LED_IDE2 2 #endif +#ifdef CONFIG_IDE_RESET +extern void ide_set_reset(int idereset); + +static void ide_reset(void) +{ + int i; + + curr_device = -1; + for (i = 0; i < CONFIG_SYS_IDE_MAXBUS; ++i) + ide_bus_ok[i] = 0; + for (i = 0; i < CONFIG_SYS_IDE_MAXDEVICE; ++i) + ide_dev_desc[i].type = DEV_TYPE_UNKNOWN; + + ide_set_reset(1); /* assert reset */ + + /* the reset signal shall be asserted for et least 25 us */ + udelay(25); + + WATCHDOG_RESET(); + + /* de-assert RESET signal */ + ide_set_reset(0); + + /* wait 250 ms */ + for (i = 0; i < 250; ++i) + udelay(1000); +} +#else +#define ide_reset() /* dummy */ +#endif /* CONFIG_IDE_RESET */ + +/* + * Wait until Busy bit is off, or timeout (in ms) + * Return last status + */ +static uchar ide_wait(int dev, ulong t) +{ + ulong delay = 10 * t; /* poll every 100 us */ + uchar c; + + while ((c = ide_inb(dev, ATA_STATUS)) & ATA_STAT_BUSY) { + udelay(100); + if (delay-- == 0) + break; + } + return c; +} + +/* + * copy src to dest, skipping leading and trailing blanks and null + * terminate the string + * "len" is the size of available memory including the terminating '\0' + */ +static void ident_cpy(unsigned char *dst, unsigned char *src, + unsigned int len) +{ + unsigned char *end, *last; + + last = dst; + end = src + len - 1; + + /* reserve space for '\0' */ + if (len < 2) + goto OUT; + + /* skip leading white space */ + while ((*src) && (src < end) && (*src == ' ')) + ++src; + + /* copy string, omitting trailing white space */ + while ((*src) && (src < end)) { + *dst++ = *src; + if (*src++ != ' ') + last = dst; + } +OUT: + *last = '\0'; +} + +#ifdef CONFIG_ATAPI +/**************************************************************************** + * ATAPI Support + */ + +#if defined(CONFIG_IDE_SWAP_IO) +/* since ATAPI may use commands with not 4 bytes alligned length + * we have our own transfer functions, 2 bytes alligned */ +__weak void ide_output_data_shorts(int dev, ushort *sect_buf, int shorts) +{ + ushort *dbuf; + volatile ushort *pbuf; + + pbuf = (ushort *)(ATA_CURR_BASE(dev) + ATA_DATA_REG); + dbuf = (ushort *)sect_buf; + + debug("in output data shorts base for read is %lx\n", + (unsigned long) pbuf); + + while (shorts--) { + EIEIO; + *pbuf = *dbuf++; + } +} + +__weak void ide_input_data_shorts(int dev, ushort *sect_buf, int shorts) +{ + ushort *dbuf; + volatile ushort *pbuf; + + pbuf = (ushort *)(ATA_CURR_BASE(dev) + ATA_DATA_REG); + dbuf = (ushort *)sect_buf; + + debug("in input data shorts base for read is %lx\n", + (unsigned long) pbuf); + + while (shorts--) { + EIEIO; + *dbuf++ = *pbuf; + } +} + +#else /* ! CONFIG_IDE_SWAP_IO */ +__weak void ide_output_data_shorts(int dev, ushort *sect_buf, int shorts) +{ + outsw(ATA_CURR_BASE(dev) + ATA_DATA_REG, sect_buf, shorts); +} + +__weak void ide_input_data_shorts(int dev, ushort *sect_buf, int shorts) +{ + insw(ATA_CURR_BASE(dev) + ATA_DATA_REG, sect_buf, shorts); +} + +#endif /* CONFIG_IDE_SWAP_IO */ + +/* + * Wait until (Status & mask) == res, or timeout (in ms) + * Return last status + * This is used since some ATAPI CD ROMs clears their Busy Bit first + * and then they set their DRQ Bit + */ +static uchar atapi_wait_mask(int dev, ulong t, uchar mask, uchar res) +{ + ulong delay = 10 * t; /* poll every 100 us */ + uchar c; + + /* prevents to read the status before valid */ + c = ide_inb(dev, ATA_DEV_CTL); + + while (((c = ide_inb(dev, ATA_STATUS)) & mask) != res) { + /* break if error occurs (doesn't make sense to wait more) */ + if ((c & ATA_STAT_ERR) == ATA_STAT_ERR) + break; + udelay(100); + if (delay-- == 0) + break; + } + return c; +} + +/* + * issue an atapi command + */ +unsigned char atapi_issue(int device, unsigned char *ccb, int ccblen, + unsigned char *buffer, int buflen) +{ + unsigned char c, err, mask, res; + int n; + + ide_led(DEVICE_LED(device), 1); /* LED on */ + + /* Select device + */ + mask = ATA_STAT_BUSY | ATA_STAT_DRQ; + res = 0; + ide_outb(device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device)); + c = atapi_wait_mask(device, ATAPI_TIME_OUT, mask, res); + if ((c & mask) != res) { + printf("ATAPI_ISSUE: device %d not ready status %X\n", device, + c); + err = 0xFF; + goto AI_OUT; + } + /* write taskfile */ + ide_outb(device, ATA_ERROR_REG, 0); /* no DMA, no overlaped */ + ide_outb(device, ATA_SECT_CNT, 0); + ide_outb(device, ATA_SECT_NUM, 0); + ide_outb(device, ATA_CYL_LOW, (unsigned char) (buflen & 0xFF)); + ide_outb(device, ATA_CYL_HIGH, + (unsigned char) ((buflen >> 8) & 0xFF)); + ide_outb(device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device)); + + ide_outb(device, ATA_COMMAND, ATAPI_CMD_PACKET); + udelay(50); + + mask = ATA_STAT_DRQ | ATA_STAT_BUSY | ATA_STAT_ERR; + res = ATA_STAT_DRQ; + c = atapi_wait_mask(device, ATAPI_TIME_OUT, mask, res); + + if ((c & mask) != res) { /* DRQ must be 1, BSY 0 */ + printf("ATAPI_ISSUE: Error (no IRQ) before sending ccb dev %d status 0x%02x\n", + device, c); + err = 0xFF; + goto AI_OUT; + } + + /* write command block */ + ide_output_data_shorts(device, (unsigned short *)ccb, ccblen / 2); + + /* ATAPI Command written wait for completition */ + udelay(5000); /* device must set bsy */ + + mask = ATA_STAT_DRQ | ATA_STAT_BUSY | ATA_STAT_ERR; + /* + * if no data wait for DRQ = 0 BSY = 0 + * if data wait for DRQ = 1 BSY = 0 + */ + res = 0; + if (buflen) + res = ATA_STAT_DRQ; + c = atapi_wait_mask(device, ATAPI_TIME_OUT, mask, res); + if ((c & mask) != res) { + if (c & ATA_STAT_ERR) { + err = (ide_inb(device, ATA_ERROR_REG)) >> 4; + debug("atapi_issue 1 returned sense key %X status %02X\n", + err, c); + } else { + printf("ATAPI_ISSUE: (no DRQ) after sending ccb (%x) status 0x%02x\n", + ccb[0], c); + err = 0xFF; + } + goto AI_OUT; + } + n = ide_inb(device, ATA_CYL_HIGH); + n <<= 8; + n += ide_inb(device, ATA_CYL_LOW); + if (n > buflen) { + printf("ERROR, transfer bytes %d requested only %d\n", n, + buflen); + err = 0xff; + goto AI_OUT; + } + if ((n == 0) && (buflen < 0)) { + printf("ERROR, transfer bytes %d requested %d\n", n, buflen); + err = 0xff; + goto AI_OUT; + } + if (n != buflen) { + debug("WARNING, transfer bytes %d not equal with requested %d\n", + n, buflen); + } + if (n != 0) { /* data transfer */ + debug("ATAPI_ISSUE: %d Bytes to transfer\n", n); + /* we transfer shorts */ + n >>= 1; + /* ok now decide if it is an in or output */ + if ((ide_inb(device, ATA_SECT_CNT) & 0x02) == 0) { + debug("Write to device\n"); + ide_output_data_shorts(device, (unsigned short *)buffer, + n); + } else { + debug("Read from device @ %p shorts %d\n", buffer, n); + ide_input_data_shorts(device, (unsigned short *)buffer, + n); + } + } + udelay(5000); /* seems that some CD ROMs need this... */ + mask = ATA_STAT_BUSY | ATA_STAT_ERR; + res = 0; + c = atapi_wait_mask(device, ATAPI_TIME_OUT, mask, res); + if ((c & ATA_STAT_ERR) == ATA_STAT_ERR) { + err = (ide_inb(device, ATA_ERROR_REG) >> 4); + debug("atapi_issue 2 returned sense key %X status %X\n", err, + c); + } else { + err = 0; + } +AI_OUT: + ide_led(DEVICE_LED(device), 0); /* LED off */ + return err; +} + +/* + * sending the command to atapi_issue. If an status other than good + * returns, an request_sense will be issued + */ + +#define ATAPI_DRIVE_NOT_READY 100 +#define ATAPI_UNIT_ATTN 10 + +unsigned char atapi_issue_autoreq(int device, + unsigned char *ccb, + int ccblen, + unsigned char *buffer, int buflen) +{ + unsigned char sense_data[18], sense_ccb[12]; + unsigned char res, key, asc, ascq; + int notready, unitattn; + + unitattn = ATAPI_UNIT_ATTN; + notready = ATAPI_DRIVE_NOT_READY; + +retry: + res = atapi_issue(device, ccb, ccblen, buffer, buflen); + if (res == 0) + return 0; /* Ok */ + + if (res == 0xFF) + return 0xFF; /* error */ + + debug("(auto_req)atapi_issue returned sense key %X\n", res); + + memset(sense_ccb, 0, sizeof(sense_ccb)); + memset(sense_data, 0, sizeof(sense_data)); + sense_ccb[0] = ATAPI_CMD_REQ_SENSE; + sense_ccb[4] = 18; /* allocation Length */ + + res = atapi_issue(device, sense_ccb, 12, sense_data, 18); + key = (sense_data[2] & 0xF); + asc = (sense_data[12]); + ascq = (sense_data[13]); + + debug("ATAPI_CMD_REQ_SENSE returned %x\n", res); + debug(" Sense page: %02X key %02X ASC %02X ASCQ %02X\n", + sense_data[0], key, asc, ascq); + + if ((key == 0)) + return 0; /* ok device ready */ + + if ((key == 6) || (asc == 0x29) || (asc == 0x28)) { /* Unit Attention */ + if (unitattn-- > 0) { + udelay(200 * 1000); + goto retry; + } + printf("Unit Attention, tried %d\n", ATAPI_UNIT_ATTN); + goto error; + } + if ((asc == 0x4) && (ascq == 0x1)) { + /* not ready, but will be ready soon */ + if (notready-- > 0) { + udelay(200 * 1000); + goto retry; + } + printf("Drive not ready, tried %d times\n", + ATAPI_DRIVE_NOT_READY); + goto error; + } + if (asc == 0x3a) { + debug("Media not present\n"); + goto error; + } + + printf("ERROR: Unknown Sense key %02X ASC %02X ASCQ %02X\n", key, asc, + ascq); +error: + debug("ERROR Sense key %02X ASC %02X ASCQ %02X\n", key, asc, ascq); + return 0xFF; +} + +/* + * atapi_read: + * we transfer only one block per command, since the multiple DRQ per + * command is not yet implemented + */ +#define ATAPI_READ_MAX_BYTES 2048 /* we read max 2kbytes */ +#define ATAPI_READ_BLOCK_SIZE 2048 /* assuming CD part */ +#define ATAPI_READ_MAX_BLOCK (ATAPI_READ_MAX_BYTES/ATAPI_READ_BLOCK_SIZE) + +ulong atapi_read(struct blk_desc *block_dev, lbaint_t blknr, lbaint_t blkcnt, + void *buffer) +{ + int device = block_dev->devnum; + ulong n = 0; + unsigned char ccb[12]; /* Command descriptor block */ + ulong cnt; + + debug("atapi_read dev %d start " LBAF " blocks " LBAF + " buffer at %lX\n", device, blknr, blkcnt, (ulong) buffer); + + do { + if (blkcnt > ATAPI_READ_MAX_BLOCK) + cnt = ATAPI_READ_MAX_BLOCK; + else + cnt = blkcnt; + + ccb[0] = ATAPI_CMD_READ_12; + ccb[1] = 0; /* reserved */ + ccb[2] = (unsigned char) (blknr >> 24) & 0xFF; /* MSB Block */ + ccb[3] = (unsigned char) (blknr >> 16) & 0xFF; /* */ + ccb[4] = (unsigned char) (blknr >> 8) & 0xFF; + ccb[5] = (unsigned char) blknr & 0xFF; /* LSB Block */ + ccb[6] = (unsigned char) (cnt >> 24) & 0xFF; /* MSB Block cnt */ + ccb[7] = (unsigned char) (cnt >> 16) & 0xFF; + ccb[8] = (unsigned char) (cnt >> 8) & 0xFF; + ccb[9] = (unsigned char) cnt & 0xFF; /* LSB Block */ + ccb[10] = 0; /* reserved */ + ccb[11] = 0; /* reserved */ + + if (atapi_issue_autoreq(device, ccb, 12, + (unsigned char *)buffer, + cnt * ATAPI_READ_BLOCK_SIZE) + == 0xFF) { + return n; + } + n += cnt; + blkcnt -= cnt; + blknr += cnt; + buffer += (cnt * ATAPI_READ_BLOCK_SIZE); + } while (blkcnt > 0); + return n; +} + +static void atapi_inquiry(struct blk_desc *dev_desc) +{ + unsigned char ccb[12]; /* Command descriptor block */ + unsigned char iobuf[64]; /* temp buf */ + unsigned char c; + int device; + + device = dev_desc->devnum; + dev_desc->type = DEV_TYPE_UNKNOWN; /* not yet valid */ + dev_desc->block_read = atapi_read; + + memset(ccb, 0, sizeof(ccb)); + memset(iobuf, 0, sizeof(iobuf)); + + ccb[0] = ATAPI_CMD_INQUIRY; + ccb[4] = 40; /* allocation Legnth */ + c = atapi_issue_autoreq(device, ccb, 12, (unsigned char *)iobuf, 40); + + debug("ATAPI_CMD_INQUIRY returned %x\n", c); + if (c != 0) + return; + + /* copy device ident strings */ + ident_cpy((unsigned char *)dev_desc->vendor, &iobuf[8], 8); + ident_cpy((unsigned char *)dev_desc->product, &iobuf[16], 16); + ident_cpy((unsigned char *)dev_desc->revision, &iobuf[32], 5); + + dev_desc->lun = 0; + dev_desc->lba = 0; + dev_desc->blksz = 0; + dev_desc->log2blksz = LOG2_INVALID(typeof(dev_desc->log2blksz)); + dev_desc->type = iobuf[0] & 0x1f; + + if ((iobuf[1] & 0x80) == 0x80) + dev_desc->removable = 1; + else + dev_desc->removable = 0; + + memset(ccb, 0, sizeof(ccb)); + memset(iobuf, 0, sizeof(iobuf)); + ccb[0] = ATAPI_CMD_START_STOP; + ccb[4] = 0x03; /* start */ + + c = atapi_issue_autoreq(device, ccb, 12, (unsigned char *)iobuf, 0); + + debug("ATAPI_CMD_START_STOP returned %x\n", c); + if (c != 0) + return; + + memset(ccb, 0, sizeof(ccb)); + memset(iobuf, 0, sizeof(iobuf)); + c = atapi_issue_autoreq(device, ccb, 12, (unsigned char *)iobuf, 0); + + debug("ATAPI_CMD_UNIT_TEST_READY returned %x\n", c); + if (c != 0) + return; + + memset(ccb, 0, sizeof(ccb)); + memset(iobuf, 0, sizeof(iobuf)); + ccb[0] = ATAPI_CMD_READ_CAP; + c = atapi_issue_autoreq(device, ccb, 12, (unsigned char *)iobuf, 8); + debug("ATAPI_CMD_READ_CAP returned %x\n", c); + if (c != 0) + return; + + debug("Read Cap: LBA %02X%02X%02X%02X blksize %02X%02X%02X%02X\n", + iobuf[0], iobuf[1], iobuf[2], iobuf[3], + iobuf[4], iobuf[5], iobuf[6], iobuf[7]); + + dev_desc->lba = ((unsigned long) iobuf[0] << 24) + + ((unsigned long) iobuf[1] << 16) + + ((unsigned long) iobuf[2] << 8) + ((unsigned long) iobuf[3]); + dev_desc->blksz = ((unsigned long) iobuf[4] << 24) + + ((unsigned long) iobuf[5] << 16) + + ((unsigned long) iobuf[6] << 8) + ((unsigned long) iobuf[7]); + dev_desc->log2blksz = LOG2(dev_desc->blksz); +#ifdef CONFIG_LBA48 + /* ATAPI devices cannot use 48bit addressing (ATA/ATAPI v7) */ + dev_desc->lba48 = 0; +#endif + return; +} + +#endif /* CONFIG_ATAPI */ + +static void ide_ident(struct blk_desc *dev_desc) +{ + unsigned char c; + hd_driveid_t iop; + +#ifdef CONFIG_ATAPI + int retries = 0; +#endif + int device; + + device = dev_desc->devnum; + printf(" Device %d: ", device); + + ide_led(DEVICE_LED(device), 1); /* LED on */ + /* Select device + */ + ide_outb(device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device)); + dev_desc->if_type = IF_TYPE_IDE; +#ifdef CONFIG_ATAPI + + retries = 0; + + /* Warning: This will be tricky to read */ + while (retries <= 1) { + /* check signature */ + if ((ide_inb(device, ATA_SECT_CNT) == 0x01) && + (ide_inb(device, ATA_SECT_NUM) == 0x01) && + (ide_inb(device, ATA_CYL_LOW) == 0x14) && + (ide_inb(device, ATA_CYL_HIGH) == 0xEB)) { + /* ATAPI Signature found */ + dev_desc->if_type = IF_TYPE_ATAPI; + /* + * Start Ident Command + */ + ide_outb(device, ATA_COMMAND, ATAPI_CMD_IDENT); + /* + * Wait for completion - ATAPI devices need more time + * to become ready + */ + c = ide_wait(device, ATAPI_TIME_OUT); + } else +#endif + { + /* + * Start Ident Command + */ + ide_outb(device, ATA_COMMAND, ATA_CMD_IDENT); + + /* + * Wait for completion + */ + c = ide_wait(device, IDE_TIME_OUT); + } + ide_led(DEVICE_LED(device), 0); /* LED off */ + + if (((c & ATA_STAT_DRQ) == 0) || + ((c & (ATA_STAT_FAULT | ATA_STAT_ERR)) != 0)) { +#ifdef CONFIG_ATAPI + { + /* + * Need to soft reset the device + * in case it's an ATAPI... + */ + debug("Retrying...\n"); + ide_outb(device, ATA_DEV_HD, + ATA_LBA | ATA_DEVICE(device)); + udelay(100000); + ide_outb(device, ATA_COMMAND, 0x08); + udelay(500000); /* 500 ms */ + } + /* + * Select device + */ + ide_outb(device, ATA_DEV_HD, + ATA_LBA | ATA_DEVICE(device)); + retries++; +#else + return; +#endif + } +#ifdef CONFIG_ATAPI + else + break; + } /* see above - ugly to read */ + + if (retries == 2) /* Not found */ + return; +#endif + + ide_input_swap_data(device, (ulong *)&iop, ATA_SECTORWORDS); + + ident_cpy((unsigned char *)dev_desc->revision, iop.fw_rev, + sizeof(dev_desc->revision)); + ident_cpy((unsigned char *)dev_desc->vendor, iop.model, + sizeof(dev_desc->vendor)); + ident_cpy((unsigned char *)dev_desc->product, iop.serial_no, + sizeof(dev_desc->product)); +#ifdef __LITTLE_ENDIAN + /* + * firmware revision, model, and serial number have Big Endian Byte + * order in Word. Convert all three to little endian. + * + * See CF+ and CompactFlash Specification Revision 2.0: + * 6.2.1.6: Identify Drive, Table 39 for more details + */ + + strswab(dev_desc->revision); + strswab(dev_desc->vendor); + strswab(dev_desc->product); +#endif /* __LITTLE_ENDIAN */ + + if ((iop.config & 0x0080) == 0x0080) + dev_desc->removable = 1; + else + dev_desc->removable = 0; + +#ifdef CONFIG_ATAPI + if (dev_desc->if_type == IF_TYPE_ATAPI) { + atapi_inquiry(dev_desc); + return; + } +#endif /* CONFIG_ATAPI */ + +#ifdef __BIG_ENDIAN + /* swap shorts */ + dev_desc->lba = (iop.lba_capacity << 16) | (iop.lba_capacity >> 16); +#else /* ! __BIG_ENDIAN */ + /* + * do not swap shorts on little endian + * + * See CF+ and CompactFlash Specification Revision 2.0: + * 6.2.1.6: Identfy Drive, Table 39, Word Address 57-58 for details. + */ + dev_desc->lba = iop.lba_capacity; +#endif /* __BIG_ENDIAN */ + +#ifdef CONFIG_LBA48 + if (iop.command_set_2 & 0x0400) { /* LBA 48 support */ + dev_desc->lba48 = 1; + dev_desc->lba = (unsigned long long) iop.lba48_capacity[0] | + ((unsigned long long) iop.lba48_capacity[1] << 16) | + ((unsigned long long) iop.lba48_capacity[2] << 32) | + ((unsigned long long) iop.lba48_capacity[3] << 48); + } else { + dev_desc->lba48 = 0; + } +#endif /* CONFIG_LBA48 */ + /* assuming HD */ + dev_desc->type = DEV_TYPE_HARDDISK; + dev_desc->blksz = ATA_BLOCKSIZE; + dev_desc->log2blksz = LOG2(dev_desc->blksz); + dev_desc->lun = 0; /* just to fill something in... */ + +#if 0 /* only used to test the powersaving mode, + * if enabled, the drive goes after 5 sec + * in standby mode */ + ide_outb(device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device)); + c = ide_wait(device, IDE_TIME_OUT); + ide_outb(device, ATA_SECT_CNT, 1); + ide_outb(device, ATA_LBA_LOW, 0); + ide_outb(device, ATA_LBA_MID, 0); + ide_outb(device, ATA_LBA_HIGH, 0); + ide_outb(device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device)); + ide_outb(device, ATA_COMMAND, 0xe3); + udelay(50); + c = ide_wait(device, IDE_TIME_OUT); /* can't take over 500 ms */ +#endif +} /* ------------------------------------------------------------------------- */ @@ -120,8 +772,8 @@ int do_ide(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) return 0; } else if (strncmp(argv[1], "dev", 3) == 0) { - if ((curr_device < 0) - || (curr_device >= CONFIG_SYS_IDE_MAXDEVICE)) { + if (curr_device < 0 || + curr_device >= CONFIG_SYS_IDE_MAXDEVICE) { puts("\nno IDE devices available\n"); return 1; } @@ -235,8 +887,8 @@ int do_ide(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) n = ide_write(&ide_dev_desc[curr_device], blk, cnt, (ulong *)addr); - printf("%ld blocks written: %s\n", - n, (n == cnt) ? "OK" : "ERROR"); + printf("%ld blocks written: %s\n", n, + n == cnt ? "OK" : "ERROR"); if (n == cnt) return 0; else @@ -272,12 +924,6 @@ __weak void ide_led(uchar led, uchar status) #endif } -#ifndef CONFIG_IDE_LED /* define LED macros, they are not used anyways */ -# define DEVICE_LED(x) 0 -# define LED_IDE1 1 -# define LED_IDE2 2 -#endif - /* ------------------------------------------------------------------------- */ __weak void ide_outb(int dev, int port, unsigned char val) @@ -465,16 +1111,16 @@ __weak void ide_input_swap_data(int dev, ulong *sect_buf, int words) __weak void ide_input_swap_data(int dev, ulong *sect_buf, int words) { volatile ushort *pbuf = - (ushort *) (ATA_CURR_BASE(dev) + ATA_DATA_REG); - ushort *dbuf = (ushort *) sect_buf; + (ushort *)(ATA_CURR_BASE(dev) + ATA_DATA_REG); + ushort *dbuf = (ushort *)sect_buf; debug("in input swap data base for read is %lx\n", (unsigned long) pbuf); while (words--) { #ifdef __MIPS__ - *dbuf++ = swab16p((u16 *) pbuf); - *dbuf++ = swab16p((u16 *) pbuf); + *dbuf++ = swab16p((u16 *)pbuf); + *dbuf++ = swab16p((u16 *)pbuf); #else *dbuf++ = ld_le16(pbuf); *dbuf++ = ld_le16(pbuf); @@ -490,8 +1136,8 @@ __weak void ide_output_data(int dev, const ulong *sect_buf, int words) ushort *dbuf; volatile ushort *pbuf; - pbuf = (ushort *) (ATA_CURR_BASE(dev) + ATA_DATA_REG); - dbuf = (ushort *) sect_buf; + pbuf = (ushort *)(ATA_CURR_BASE(dev) + ATA_DATA_REG); + dbuf = (ushort *)sect_buf; while (words--) { EIEIO; *pbuf = *dbuf++; @@ -516,8 +1162,8 @@ __weak void ide_input_data(int dev, ulong *sect_buf, int words) ushort *dbuf; volatile ushort *pbuf; - pbuf = (ushort *) (ATA_CURR_BASE(dev) + ATA_DATA_REG); - dbuf = (ushort *) sect_buf; + pbuf = (ushort *)(ATA_CURR_BASE(dev) + ATA_DATA_REG); + dbuf = (ushort *)sect_buf; debug("in input data base for read is %lx\n", (unsigned long) pbuf); @@ -540,178 +1186,6 @@ __weak void ide_input_data(int dev, ulong *sect_buf, int words) #endif /* CONFIG_IDE_SWAP_IO */ -/* ------------------------------------------------------------------------- - */ -static void ide_ident(struct blk_desc *dev_desc) -{ - unsigned char c; - hd_driveid_t iop; - -#ifdef CONFIG_ATAPI - int retries = 0; -#endif - int device; - - device = dev_desc->devnum; - printf(" Device %d: ", device); - - ide_led(DEVICE_LED(device), 1); /* LED on */ - /* Select device - */ - ide_outb(device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device)); - dev_desc->if_type = IF_TYPE_IDE; -#ifdef CONFIG_ATAPI - - retries = 0; - - /* Warning: This will be tricky to read */ - while (retries <= 1) { - /* check signature */ - if ((ide_inb(device, ATA_SECT_CNT) == 0x01) && - (ide_inb(device, ATA_SECT_NUM) == 0x01) && - (ide_inb(device, ATA_CYL_LOW) == 0x14) && - (ide_inb(device, ATA_CYL_HIGH) == 0xEB)) { - /* ATAPI Signature found */ - dev_desc->if_type = IF_TYPE_ATAPI; - /* - * Start Ident Command - */ - ide_outb(device, ATA_COMMAND, ATAPI_CMD_IDENT); - /* - * Wait for completion - ATAPI devices need more time - * to become ready - */ - c = ide_wait(device, ATAPI_TIME_OUT); - } else -#endif - { - /* - * Start Ident Command - */ - ide_outb(device, ATA_COMMAND, ATA_CMD_IDENT); - - /* - * Wait for completion - */ - c = ide_wait(device, IDE_TIME_OUT); - } - ide_led(DEVICE_LED(device), 0); /* LED off */ - - if (((c & ATA_STAT_DRQ) == 0) || - ((c & (ATA_STAT_FAULT | ATA_STAT_ERR)) != 0)) { -#ifdef CONFIG_ATAPI - { - /* - * Need to soft reset the device - * in case it's an ATAPI... - */ - debug("Retrying...\n"); - ide_outb(device, ATA_DEV_HD, - ATA_LBA | ATA_DEVICE(device)); - udelay(100000); - ide_outb(device, ATA_COMMAND, 0x08); - udelay(500000); /* 500 ms */ - } - /* - * Select device - */ - ide_outb(device, ATA_DEV_HD, - ATA_LBA | ATA_DEVICE(device)); - retries++; -#else - return; -#endif - } -#ifdef CONFIG_ATAPI - else - break; - } /* see above - ugly to read */ - - if (retries == 2) /* Not found */ - return; -#endif - - ide_input_swap_data(device, (ulong *)&iop, ATA_SECTORWORDS); - - ident_cpy((unsigned char *) dev_desc->revision, iop.fw_rev, - sizeof(dev_desc->revision)); - ident_cpy((unsigned char *) dev_desc->vendor, iop.model, - sizeof(dev_desc->vendor)); - ident_cpy((unsigned char *) dev_desc->product, iop.serial_no, - sizeof(dev_desc->product)); -#ifdef __LITTLE_ENDIAN - /* - * firmware revision, model, and serial number have Big Endian Byte - * order in Word. Convert all three to little endian. - * - * See CF+ and CompactFlash Specification Revision 2.0: - * 6.2.1.6: Identify Drive, Table 39 for more details - */ - - strswab(dev_desc->revision); - strswab(dev_desc->vendor); - strswab(dev_desc->product); -#endif /* __LITTLE_ENDIAN */ - - if ((iop.config & 0x0080) == 0x0080) - dev_desc->removable = 1; - else - dev_desc->removable = 0; - -#ifdef CONFIG_ATAPI - if (dev_desc->if_type == IF_TYPE_ATAPI) { - atapi_inquiry(dev_desc); - return; - } -#endif /* CONFIG_ATAPI */ - -#ifdef __BIG_ENDIAN - /* swap shorts */ - dev_desc->lba = (iop.lba_capacity << 16) | (iop.lba_capacity >> 16); -#else /* ! __BIG_ENDIAN */ - /* - * do not swap shorts on little endian - * - * See CF+ and CompactFlash Specification Revision 2.0: - * 6.2.1.6: Identfy Drive, Table 39, Word Address 57-58 for details. - */ - dev_desc->lba = iop.lba_capacity; -#endif /* __BIG_ENDIAN */ - -#ifdef CONFIG_LBA48 - if (iop.command_set_2 & 0x0400) { /* LBA 48 support */ - dev_desc->lba48 = 1; - dev_desc->lba = (unsigned long long) iop.lba48_capacity[0] | - ((unsigned long long) iop.lba48_capacity[1] << 16) | - ((unsigned long long) iop.lba48_capacity[2] << 32) | - ((unsigned long long) iop.lba48_capacity[3] << 48); - } else { - dev_desc->lba48 = 0; - } -#endif /* CONFIG_LBA48 */ - /* assuming HD */ - dev_desc->type = DEV_TYPE_HARDDISK; - dev_desc->blksz = ATA_BLOCKSIZE; - dev_desc->log2blksz = LOG2(dev_desc->blksz); - dev_desc->lun = 0; /* just to fill something in... */ - -#if 0 /* only used to test the powersaving mode, - * if enabled, the drive goes after 5 sec - * in standby mode */ - ide_outb(device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device)); - c = ide_wait(device, IDE_TIME_OUT); - ide_outb(device, ATA_SECT_CNT, 1); - ide_outb(device, ATA_LBA_LOW, 0); - ide_outb(device, ATA_LBA_MID, 0); - ide_outb(device, ATA_LBA_HIGH, 0); - ide_outb(device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device)); - ide_outb(device, ATA_COMMAND, 0xe3); - udelay(50); - c = ide_wait(device, IDE_TIME_OUT); /* can't take over 500 ms */ -#endif -} - - /* ------------------------------------------------------------------------- */ ulong ide_read(struct blk_desc *block_dev, lbaint_t blknr, lbaint_t blkcnt, @@ -820,8 +1294,8 @@ ulong ide_read(struct blk_desc *block_dev, lbaint_t blknr, lbaint_t blkcnt, if ((c & (ATA_STAT_DRQ | ATA_STAT_BUSY | ATA_STAT_ERR)) != ATA_STAT_DRQ) { - printf("Error (no IRQ) dev %d blk " LBAF ": status " - "%#02x\n", device, blknr, c); + printf("Error (no IRQ) dev %d blk " LBAF + ": status %#02x\n", device, blknr, c); break; } @@ -863,7 +1337,6 @@ ulong ide_write(struct blk_desc *block_dev, lbaint_t blknr, lbaint_t blkcnt, ide_outb(device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device)); while (blkcnt-- > 0) { - c = ide_wait(device, IDE_TIME_OUT); if (c & ATA_STAT_BUSY) { @@ -910,8 +1383,8 @@ ulong ide_write(struct blk_desc *block_dev, lbaint_t blknr, lbaint_t blkcnt, if ((c & (ATA_STAT_DRQ | ATA_STAT_BUSY | ATA_STAT_ERR)) != ATA_STAT_DRQ) { - printf("Error (no IRQ) dev %d blk " LBAF ": status " - "%#02x\n", device, blknr, c); + printf("Error (no IRQ) dev %d blk " LBAF + ": status %#02x\n", device, blknr, c); goto WR_OUT; } @@ -928,521 +1401,16 @@ WR_OUT: /* ------------------------------------------------------------------------- */ -/* - * copy src to dest, skipping leading and trailing blanks and null - * terminate the string - * "len" is the size of available memory including the terminating '\0' - */ -static void ident_cpy(unsigned char *dst, unsigned char *src, - unsigned int len) -{ - unsigned char *end, *last; - - last = dst; - end = src + len - 1; - - /* reserve space for '\0' */ - if (len < 2) - goto OUT; - - /* skip leading white space */ - while ((*src) && (src < end) && (*src == ' ')) - ++src; - - /* copy string, omitting trailing white space */ - while ((*src) && (src < end)) { - *dst++ = *src; - if (*src++ != ' ') - last = dst; - } -OUT: - *last = '\0'; -} - -/* ------------------------------------------------------------------------- */ - -/* - * Wait until Busy bit is off, or timeout (in ms) - * Return last status - */ -static uchar ide_wait(int dev, ulong t) -{ - ulong delay = 10 * t; /* poll every 100 us */ - uchar c; - - while ((c = ide_inb(dev, ATA_STATUS)) & ATA_STAT_BUSY) { - udelay(100); - if (delay-- == 0) - break; - } - return c; -} - -/* ------------------------------------------------------------------------- */ - -#ifdef CONFIG_IDE_RESET -extern void ide_set_reset(int idereset); - -static void ide_reset(void) -{ - int i; - - curr_device = -1; - for (i = 0; i < CONFIG_SYS_IDE_MAXBUS; ++i) - ide_bus_ok[i] = 0; - for (i = 0; i < CONFIG_SYS_IDE_MAXDEVICE; ++i) - ide_dev_desc[i].type = DEV_TYPE_UNKNOWN; - - ide_set_reset(1); /* assert reset */ - - /* the reset signal shall be asserted for et least 25 us */ - udelay(25); - - WATCHDOG_RESET(); - - /* de-assert RESET signal */ - ide_set_reset(0); - - /* wait 250 ms */ - for (i = 0; i < 250; ++i) - udelay(1000); -} - -#endif /* CONFIG_IDE_RESET */ - -/* ------------------------------------------------------------------------- */ - #if defined(CONFIG_OF_IDE_FIXUP) int ide_device_present(int dev) { if (dev >= CONFIG_SYS_IDE_MAXBUS) return 0; - return (ide_dev_desc[dev].type == DEV_TYPE_UNKNOWN ? 0 : 1); + return ide_dev_desc[dev].type == DEV_TYPE_UNKNOWN ? 0 : 1; } #endif /* ------------------------------------------------------------------------- */ -#ifdef CONFIG_ATAPI -/**************************************************************************** - * ATAPI Support - */ - -#if defined(CONFIG_IDE_SWAP_IO) -/* since ATAPI may use commands with not 4 bytes alligned length - * we have our own transfer functions, 2 bytes alligned */ -__weak void ide_output_data_shorts(int dev, ushort *sect_buf, int shorts) -{ - ushort *dbuf; - volatile ushort *pbuf; - - pbuf = (ushort *) (ATA_CURR_BASE(dev) + ATA_DATA_REG); - dbuf = (ushort *) sect_buf; - - debug("in output data shorts base for read is %lx\n", - (unsigned long) pbuf); - - while (shorts--) { - EIEIO; - *pbuf = *dbuf++; - } -} - -__weak void ide_input_data_shorts(int dev, ushort *sect_buf, int shorts) -{ - ushort *dbuf; - volatile ushort *pbuf; - - pbuf = (ushort *) (ATA_CURR_BASE(dev) + ATA_DATA_REG); - dbuf = (ushort *) sect_buf; - - debug("in input data shorts base for read is %lx\n", - (unsigned long) pbuf); - - while (shorts--) { - EIEIO; - *dbuf++ = *pbuf; - } -} - -#else /* ! CONFIG_IDE_SWAP_IO */ -__weak void ide_output_data_shorts(int dev, ushort *sect_buf, int shorts) -{ - outsw(ATA_CURR_BASE(dev) + ATA_DATA_REG, sect_buf, shorts); -} - -__weak void ide_input_data_shorts(int dev, ushort *sect_buf, int shorts) -{ - insw(ATA_CURR_BASE(dev) + ATA_DATA_REG, sect_buf, shorts); -} - -#endif /* CONFIG_IDE_SWAP_IO */ - -/* - * Wait until (Status & mask) == res, or timeout (in ms) - * Return last status - * This is used since some ATAPI CD ROMs clears their Busy Bit first - * and then they set their DRQ Bit - */ -static uchar atapi_wait_mask(int dev, ulong t, uchar mask, uchar res) -{ - ulong delay = 10 * t; /* poll every 100 us */ - uchar c; - - /* prevents to read the status before valid */ - c = ide_inb(dev, ATA_DEV_CTL); - - while (((c = ide_inb(dev, ATA_STATUS)) & mask) != res) { - /* break if error occurs (doesn't make sense to wait more) */ - if ((c & ATA_STAT_ERR) == ATA_STAT_ERR) - break; - udelay(100); - if (delay-- == 0) - break; - } - return c; -} - -/* - * issue an atapi command - */ -unsigned char atapi_issue(int device, unsigned char *ccb, int ccblen, - unsigned char *buffer, int buflen) -{ - unsigned char c, err, mask, res; - int n; - - ide_led(DEVICE_LED(device), 1); /* LED on */ - - /* Select device - */ - mask = ATA_STAT_BUSY | ATA_STAT_DRQ; - res = 0; - ide_outb(device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device)); - c = atapi_wait_mask(device, ATAPI_TIME_OUT, mask, res); - if ((c & mask) != res) { - printf("ATAPI_ISSUE: device %d not ready status %X\n", device, - c); - err = 0xFF; - goto AI_OUT; - } - /* write taskfile */ - ide_outb(device, ATA_ERROR_REG, 0); /* no DMA, no overlaped */ - ide_outb(device, ATA_SECT_CNT, 0); - ide_outb(device, ATA_SECT_NUM, 0); - ide_outb(device, ATA_CYL_LOW, (unsigned char) (buflen & 0xFF)); - ide_outb(device, ATA_CYL_HIGH, - (unsigned char) ((buflen >> 8) & 0xFF)); - ide_outb(device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device)); - - ide_outb(device, ATA_COMMAND, ATAPI_CMD_PACKET); - udelay(50); - - mask = ATA_STAT_DRQ | ATA_STAT_BUSY | ATA_STAT_ERR; - res = ATA_STAT_DRQ; - c = atapi_wait_mask(device, ATAPI_TIME_OUT, mask, res); - - if ((c & mask) != res) { /* DRQ must be 1, BSY 0 */ - printf("ATAPI_ISSUE: Error (no IRQ) before sending ccb dev %d status 0x%02x\n", - device, c); - err = 0xFF; - goto AI_OUT; - } - - /* write command block */ - ide_output_data_shorts(device, (unsigned short *) ccb, ccblen / 2); - - /* ATAPI Command written wait for completition */ - udelay(5000); /* device must set bsy */ - - mask = ATA_STAT_DRQ | ATA_STAT_BUSY | ATA_STAT_ERR; - /* - * if no data wait for DRQ = 0 BSY = 0 - * if data wait for DRQ = 1 BSY = 0 - */ - res = 0; - if (buflen) - res = ATA_STAT_DRQ; - c = atapi_wait_mask(device, ATAPI_TIME_OUT, mask, res); - if ((c & mask) != res) { - if (c & ATA_STAT_ERR) { - err = (ide_inb(device, ATA_ERROR_REG)) >> 4; - debug("atapi_issue 1 returned sense key %X status %02X\n", - err, c); - } else { - printf("ATAPI_ISSUE: (no DRQ) after sending ccb (%x) status 0x%02x\n", - ccb[0], c); - err = 0xFF; - } - goto AI_OUT; - } - n = ide_inb(device, ATA_CYL_HIGH); - n <<= 8; - n += ide_inb(device, ATA_CYL_LOW); - if (n > buflen) { - printf("ERROR, transfer bytes %d requested only %d\n", n, - buflen); - err = 0xff; - goto AI_OUT; - } - if ((n == 0) && (buflen < 0)) { - printf("ERROR, transfer bytes %d requested %d\n", n, buflen); - err = 0xff; - goto AI_OUT; - } - if (n != buflen) { - debug("WARNING, transfer bytes %d not equal with requested %d\n", - n, buflen); - } - if (n != 0) { /* data transfer */ - debug("ATAPI_ISSUE: %d Bytes to transfer\n", n); - /* we transfer shorts */ - n >>= 1; - /* ok now decide if it is an in or output */ - if ((ide_inb(device, ATA_SECT_CNT) & 0x02) == 0) { - debug("Write to device\n"); - ide_output_data_shorts(device, - (unsigned short *) buffer, n); - } else { - debug("Read from device @ %p shorts %d\n", buffer, n); - ide_input_data_shorts(device, - (unsigned short *) buffer, n); - } - } - udelay(5000); /* seems that some CD ROMs need this... */ - mask = ATA_STAT_BUSY | ATA_STAT_ERR; - res = 0; - c = atapi_wait_mask(device, ATAPI_TIME_OUT, mask, res); - if ((c & ATA_STAT_ERR) == ATA_STAT_ERR) { - err = (ide_inb(device, ATA_ERROR_REG) >> 4); - debug("atapi_issue 2 returned sense key %X status %X\n", err, - c); - } else { - err = 0; - } -AI_OUT: - ide_led(DEVICE_LED(device), 0); /* LED off */ - return err; -} - -/* - * sending the command to atapi_issue. If an status other than good - * returns, an request_sense will be issued - */ - -#define ATAPI_DRIVE_NOT_READY 100 -#define ATAPI_UNIT_ATTN 10 - -unsigned char atapi_issue_autoreq(int device, - unsigned char *ccb, - int ccblen, - unsigned char *buffer, int buflen) -{ - unsigned char sense_data[18], sense_ccb[12]; - unsigned char res, key, asc, ascq; - int notready, unitattn; - - unitattn = ATAPI_UNIT_ATTN; - notready = ATAPI_DRIVE_NOT_READY; - -retry: - res = atapi_issue(device, ccb, ccblen, buffer, buflen); - if (res == 0) - return 0; /* Ok */ - - if (res == 0xFF) - return 0xFF; /* error */ - - debug("(auto_req)atapi_issue returned sense key %X\n", res); - - memset(sense_ccb, 0, sizeof(sense_ccb)); - memset(sense_data, 0, sizeof(sense_data)); - sense_ccb[0] = ATAPI_CMD_REQ_SENSE; - sense_ccb[4] = 18; /* allocation Length */ - - res = atapi_issue(device, sense_ccb, 12, sense_data, 18); - key = (sense_data[2] & 0xF); - asc = (sense_data[12]); - ascq = (sense_data[13]); - - debug("ATAPI_CMD_REQ_SENSE returned %x\n", res); - debug(" Sense page: %02X key %02X ASC %02X ASCQ %02X\n", - sense_data[0], key, asc, ascq); - - if ((key == 0)) - return 0; /* ok device ready */ - - if ((key == 6) || (asc == 0x29) || (asc == 0x28)) { /* Unit Attention */ - if (unitattn-- > 0) { - udelay(200 * 1000); - goto retry; - } - printf("Unit Attention, tried %d\n", ATAPI_UNIT_ATTN); - goto error; - } - if ((asc == 0x4) && (ascq == 0x1)) { - /* not ready, but will be ready soon */ - if (notready-- > 0) { - udelay(200 * 1000); - goto retry; - } - printf("Drive not ready, tried %d times\n", - ATAPI_DRIVE_NOT_READY); - goto error; - } - if (asc == 0x3a) { - debug("Media not present\n"); - goto error; - } - - printf("ERROR: Unknown Sense key %02X ASC %02X ASCQ %02X\n", key, asc, - ascq); -error: - debug("ERROR Sense key %02X ASC %02X ASCQ %02X\n", key, asc, ascq); - return 0xFF; -} - - -static void atapi_inquiry(struct blk_desc *dev_desc) -{ - unsigned char ccb[12]; /* Command descriptor block */ - unsigned char iobuf[64]; /* temp buf */ - unsigned char c; - int device; - - device = dev_desc->devnum; - dev_desc->type = DEV_TYPE_UNKNOWN; /* not yet valid */ - dev_desc->block_read = atapi_read; - - memset(ccb, 0, sizeof(ccb)); - memset(iobuf, 0, sizeof(iobuf)); - - ccb[0] = ATAPI_CMD_INQUIRY; - ccb[4] = 40; /* allocation Legnth */ - c = atapi_issue_autoreq(device, ccb, 12, (unsigned char *) iobuf, 40); - - debug("ATAPI_CMD_INQUIRY returned %x\n", c); - if (c != 0) - return; - - /* copy device ident strings */ - ident_cpy((unsigned char *) dev_desc->vendor, &iobuf[8], 8); - ident_cpy((unsigned char *) dev_desc->product, &iobuf[16], 16); - ident_cpy((unsigned char *) dev_desc->revision, &iobuf[32], 5); - - dev_desc->lun = 0; - dev_desc->lba = 0; - dev_desc->blksz = 0; - dev_desc->log2blksz = LOG2_INVALID(typeof(dev_desc->log2blksz)); - dev_desc->type = iobuf[0] & 0x1f; - - if ((iobuf[1] & 0x80) == 0x80) - dev_desc->removable = 1; - else - dev_desc->removable = 0; - - memset(ccb, 0, sizeof(ccb)); - memset(iobuf, 0, sizeof(iobuf)); - ccb[0] = ATAPI_CMD_START_STOP; - ccb[4] = 0x03; /* start */ - - c = atapi_issue_autoreq(device, ccb, 12, (unsigned char *) iobuf, 0); - - debug("ATAPI_CMD_START_STOP returned %x\n", c); - if (c != 0) - return; - - memset(ccb, 0, sizeof(ccb)); - memset(iobuf, 0, sizeof(iobuf)); - c = atapi_issue_autoreq(device, ccb, 12, (unsigned char *) iobuf, 0); - - debug("ATAPI_CMD_UNIT_TEST_READY returned %x\n", c); - if (c != 0) - return; - - memset(ccb, 0, sizeof(ccb)); - memset(iobuf, 0, sizeof(iobuf)); - ccb[0] = ATAPI_CMD_READ_CAP; - c = atapi_issue_autoreq(device, ccb, 12, (unsigned char *) iobuf, 8); - debug("ATAPI_CMD_READ_CAP returned %x\n", c); - if (c != 0) - return; - - debug("Read Cap: LBA %02X%02X%02X%02X blksize %02X%02X%02X%02X\n", - iobuf[0], iobuf[1], iobuf[2], iobuf[3], - iobuf[4], iobuf[5], iobuf[6], iobuf[7]); - - dev_desc->lba = ((unsigned long) iobuf[0] << 24) + - ((unsigned long) iobuf[1] << 16) + - ((unsigned long) iobuf[2] << 8) + ((unsigned long) iobuf[3]); - dev_desc->blksz = ((unsigned long) iobuf[4] << 24) + - ((unsigned long) iobuf[5] << 16) + - ((unsigned long) iobuf[6] << 8) + ((unsigned long) iobuf[7]); - dev_desc->log2blksz = LOG2(dev_desc->blksz); -#ifdef CONFIG_LBA48 - /* ATAPI devices cannot use 48bit addressing (ATA/ATAPI v7) */ - dev_desc->lba48 = 0; -#endif - return; -} - - -/* - * atapi_read: - * we transfer only one block per command, since the multiple DRQ per - * command is not yet implemented - */ -#define ATAPI_READ_MAX_BYTES 2048 /* we read max 2kbytes */ -#define ATAPI_READ_BLOCK_SIZE 2048 /* assuming CD part */ -#define ATAPI_READ_MAX_BLOCK (ATAPI_READ_MAX_BYTES/ATAPI_READ_BLOCK_SIZE) - -ulong atapi_read(struct blk_desc *block_dev, lbaint_t blknr, lbaint_t blkcnt, - void *buffer) -{ - int device = block_dev->devnum; - ulong n = 0; - unsigned char ccb[12]; /* Command descriptor block */ - ulong cnt; - - debug("atapi_read dev %d start " LBAF " blocks " LBAF - " buffer at %lX\n", device, blknr, blkcnt, (ulong) buffer); - - do { - if (blkcnt > ATAPI_READ_MAX_BLOCK) - cnt = ATAPI_READ_MAX_BLOCK; - else - cnt = blkcnt; - - ccb[0] = ATAPI_CMD_READ_12; - ccb[1] = 0; /* reserved */ - ccb[2] = (unsigned char) (blknr >> 24) & 0xFF; /* MSB Block */ - ccb[3] = (unsigned char) (blknr >> 16) & 0xFF; /* */ - ccb[4] = (unsigned char) (blknr >> 8) & 0xFF; - ccb[5] = (unsigned char) blknr & 0xFF; /* LSB Block */ - ccb[6] = (unsigned char) (cnt >> 24) & 0xFF; /* MSB Block cnt */ - ccb[7] = (unsigned char) (cnt >> 16) & 0xFF; - ccb[8] = (unsigned char) (cnt >> 8) & 0xFF; - ccb[9] = (unsigned char) cnt & 0xFF; /* LSB Block */ - ccb[10] = 0; /* reserved */ - ccb[11] = 0; /* reserved */ - - if (atapi_issue_autoreq(device, ccb, 12, - (unsigned char *) buffer, - cnt * ATAPI_READ_BLOCK_SIZE) - == 0xFF) { - return n; - } - n += cnt; - blkcnt -= cnt; - blknr += cnt; - buffer += (cnt * ATAPI_READ_BLOCK_SIZE); - } while (blkcnt > 0); - return n; -} - -/* ------------------------------------------------------------------------- */ - -#endif /* CONFIG_ATAPI */ - U_BOOT_CMD(ide, 5, 1, do_ide, "IDE sub-system", "reset - reset IDE controller\n" From 2765c4d147011c9ac80cc014661321829056ee25 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 1 May 2016 11:36:01 -0600 Subject: [PATCH 049/162] dm: sata: Fix code style problems in cmd/sata.c This file has a few coding style problems. Fix these to make future updates easier. Signed-off-by: Simon Glass --- cmd/sata.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/cmd/sata.c b/cmd/sata.c index 8748ccef69..b1a64d9969 100644 --- a/cmd/sata.c +++ b/cmd/sata.c @@ -105,25 +105,27 @@ static int do_sata(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) case 1: return CMD_RET_USAGE; case 2: - if (strncmp(argv[1],"inf", 3) == 0) { + if (strncmp(argv[1], "inf", 3) == 0) { int i; + putc('\n'); for (i = 0; i < CONFIG_SYS_SATA_MAX_DEVICE; ++i) { if (sata_dev_desc[i].type == DEV_TYPE_UNKNOWN) continue; - printf ("SATA device %d: ", i); + printf("SATA device %d: ", i); dev_print(&sata_dev_desc[i]); } return 0; - } else if (strncmp(argv[1],"dev", 3) == 0) { - if ((sata_curr_device < 0) || (sata_curr_device >= CONFIG_SYS_SATA_MAX_DEVICE)) { + } else if (strncmp(argv[1], "dev", 3) == 0) { + if (sata_curr_device < 0 || + sata_curr_device >= CONFIG_SYS_SATA_MAX_DEVICE) { puts("\nno SATA devices available\n"); return 1; } printf("\nSATA device %d: ", sata_curr_device); dev_print(&sata_dev_desc[sata_curr_device]); return 0; - } else if (strncmp(argv[1],"part",4) == 0) { + } else if (strncmp(argv[1], "part", 4) == 0) { int dev, ok; for (ok = 0, dev = 0; dev < CONFIG_SYS_SATA_MAX_DEVICE; ++dev) { From c649e3c91cdc96a86ca2665fcfafaca5c4b384b1 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 1 May 2016 11:36:02 -0600 Subject: [PATCH 050/162] dm: scsi: Rename CONFIG_CMD_SCSI to CONFIG_SCSI This option currently enables both the command and the SCSI functionality. Rename the existing option to CONFIG_SCSI since most of the code relates to the feature. Signed-off-by: Simon Glass --- README | 4 ++-- api/api_storage.c | 2 +- arch/arm/include/asm/arch-ls102xa/config.h | 2 +- board/mpl/pip405/README | 6 +++--- cmd/Makefile | 4 ++-- cmd/disk.c | 2 +- common/board_r.c | 4 ++-- disk/part.c | 2 +- drivers/block/sym53c8xx.c | 2 +- fs/fat/fat.c | 2 +- include/config_cmd_all.h | 2 +- include/config_distro_bootcmd.h | 6 +++--- include/config_fallbacks.h | 2 +- include/configs/MPC8544DS.h | 2 +- include/configs/MPC8572DS.h | 2 +- include/configs/MPC8610HPCD.h | 2 +- include/configs/MPC8641HPCN.h | 2 +- include/configs/PIP405.h | 2 +- include/configs/am57xx_evm.h | 2 +- include/configs/cm_t54.h | 2 +- include/configs/db-88f6820-gp.h | 2 +- include/configs/dra7xx_evm.h | 2 +- include/configs/efi-x86.h | 2 +- include/configs/galileo.h | 2 +- include/configs/highbank.h | 2 +- include/configs/ls1043aqds.h | 2 +- include/configs/ls2080aqds.h | 2 +- include/configs/ls2080ardb.h | 2 +- include/configs/omap5_uevm.h | 2 +- include/configs/qemu-x86.h | 2 +- include/configs/sunxi-common.h | 2 +- include/configs/x86-common.h | 2 +- include/configs/xilinx_zynqmp.h | 2 +- 33 files changed, 40 insertions(+), 40 deletions(-) diff --git a/README b/README index 88ff837d7c..33dc788474 100644 --- a/README +++ b/README @@ -1066,7 +1066,7 @@ The following options need to be configured: CONFIG_CMD_RUN run command in env variable CONFIG_CMD_SANDBOX * sb command to access sandbox features CONFIG_CMD_SAVES * save S record dump - CONFIG_CMD_SCSI * SCSI Support + CONFIG_SCSI * SCSI Support CONFIG_CMD_SDRAM * print SDRAM configuration information (requires CONFIG_CMD_I2C) CONFIG_CMD_SETGETDCR Support for DCR Register access @@ -1254,7 +1254,7 @@ The following options need to be configured: CONFIG_MTD_PARTITIONS Memory Technology Device partition table. If IDE or SCSI support is enabled (CONFIG_CMD_IDE or - CONFIG_CMD_SCSI) you must configure support for at + CONFIG_SCSI) you must configure support for at least one non-MTD partition type as well. - IDE Reset method: diff --git a/api/api_storage.c b/api/api_storage.c index 8c30c56e49..d425a9ad1d 100644 --- a/api/api_storage.c +++ b/api/api_storage.c @@ -67,7 +67,7 @@ void dev_stor_init(void) specs[ENUM_SATA].type = DEV_TYP_STOR | DT_STOR_SATA; specs[ENUM_SATA].name = "sata"; #endif -#if defined(CONFIG_CMD_SCSI) +#if defined(CONFIG_SCSI) specs[ENUM_SCSI].max_dev = CONFIG_SYS_SCSI_MAX_DEVICE; specs[ENUM_SCSI].enum_started = 0; specs[ENUM_SCSI].enum_ended = 0; diff --git a/arch/arm/include/asm/arch-ls102xa/config.h b/arch/arm/include/asm/arch-ls102xa/config.h index 267bd17727..d77c04a86a 100644 --- a/arch/arm/include/asm/arch-ls102xa/config.h +++ b/arch/arm/include/asm/arch-ls102xa/config.h @@ -82,7 +82,7 @@ /* SATA */ #define AHCI_BASE_ADDR (CONFIG_SYS_IMMR + 0x02200000) #define CONFIG_BOARD_LATE_INIT -#define CONFIG_CMD_SCSI +#define CONFIG_SCSI #define CONFIG_LIBATA #define CONFIG_SCSI_AHCI #define CONFIG_SCSI_AHCI_PLAT diff --git a/board/mpl/pip405/README b/board/mpl/pip405/README index e900c56f15..f039817b79 100644 --- a/board/mpl/pip405/README +++ b/board/mpl/pip405/README @@ -32,8 +32,8 @@ Changed files: - include/cmd_bsp.h added PIP405 commands definitions - include/cmd_condefs.h added Floppy and SCSI support - include/cmd_disk.h changed to work with block device description -- include/config_LANTEC.h excluded CONFIG_CMD_FDC and CONFIG_CMD_SCSI -- include/config_hymod.h excluded CONFIG_CMD_FDC and CONFIG_CMD_SCSI +- include/config_LANTEC.h excluded CONFIG_CMD_FDC and CONFIG_SCSI +- include/config_hymod.h excluded CONFIG_CMD_FDC and CONFIG_SCSI - include/flash.h added INTEL_ID_28F320C3T 0x88C488C4 - include/i2c.h added "defined(CONFIG_PIP405)" - include/image.h added IH_OS_U_BOOT, IH_TYPE_FIRMWARE @@ -86,7 +86,7 @@ section "Changes". New Commands: ------------- -CONFIG_CMD_SCSI SCSI Support +CONFIG_SCSI SCSI Support CONFIG_CMF_FDC Floppy disk support IDE additions: diff --git a/cmd/Makefile b/cmd/Makefile index f95759e670..6612a3b2b5 100644 --- a/cmd/Makefile +++ b/cmd/Makefile @@ -112,7 +112,7 @@ obj-$(CONFIG_CMD_REMOTEPROC) += remoteproc.o obj-$(CONFIG_SANDBOX) += host.o obj-$(CONFIG_CMD_SATA) += sata.o obj-$(CONFIG_CMD_SF) += sf.o -obj-$(CONFIG_CMD_SCSI) += scsi.o +obj-$(CONFIG_SCSI) += scsi.o obj-$(CONFIG_CMD_SHA1SUM) += sha1sum.o obj-$(CONFIG_CMD_SETEXPR) += setexpr.o obj-$(CONFIG_CMD_SOFTSWITCH) += softswitch.o @@ -157,7 +157,7 @@ endif # !CONFIG_SPL_BUILD ifdef CONFIG_SPL_BUILD ifdef CONFIG_SPL_SATA_SUPPORT -obj-$(CONFIG_CMD_SCSI) += scsi.o +obj-$(CONFIG_SCSI) += scsi.o endif endif # CONFIG_SPL_BUILD diff --git a/cmd/disk.c b/cmd/disk.c index 2fd1717e6a..fcc4123127 100644 --- a/cmd/disk.c +++ b/cmd/disk.c @@ -8,7 +8,7 @@ #include #include -#if defined(CONFIG_CMD_IDE) || defined(CONFIG_CMD_SCSI) || \ +#if defined(CONFIG_CMD_IDE) || defined(CONFIG_SCSI) || \ defined(CONFIG_USB_STORAGE) int common_diskboot(cmd_tbl_t *cmdtp, const char *intf, int argc, char *const argv[]) diff --git a/common/board_r.c b/common/board_r.c index ad02549311..d959ad3c6f 100644 --- a/common/board_r.c +++ b/common/board_r.c @@ -620,7 +620,7 @@ static int initr_ambapp_print(void) } #endif -#if defined(CONFIG_CMD_SCSI) +#if defined(CONFIG_SCSI) static int initr_scsi(void) { puts("SCSI: "); @@ -923,7 +923,7 @@ init_fnc_t init_sequence_r[] = { initr_ambapp_print, #endif #endif -#ifdef CONFIG_CMD_SCSI +#ifdef CONFIG_SCSI INIT_FUNC_WATCHDOG_RESET initr_scsi, #endif diff --git a/disk/part.c b/disk/part.c index 543cab8103..2613bff22c 100644 --- a/disk/part.c +++ b/disk/part.c @@ -28,7 +28,7 @@ const struct block_drvr block_drvr[] = { #if defined(CONFIG_CMD_SATA) {.name = "sata", .get_dev = sata_get_dev, }, #endif -#if defined(CONFIG_CMD_SCSI) +#if defined(CONFIG_SCSI) { .name = "scsi", .get_dev = scsi_get_dev, }, #endif #if defined(CONFIG_CMD_USB) && defined(CONFIG_USB_STORAGE) diff --git a/drivers/block/sym53c8xx.c b/drivers/block/sym53c8xx.c index c7c40affae..5daede7279 100644 --- a/drivers/block/sym53c8xx.c +++ b/drivers/block/sym53c8xx.c @@ -33,7 +33,7 @@ #define PRINTF(fmt,args...) #endif -#if defined(CONFIG_CMD_SCSI) && defined(CONFIG_SCSI_SYM53C8XX) +#if defined(CONFIG_SCSI) && defined(CONFIG_SCSI_SYM53C8XX) #undef SCSI_SINGLE_STEP /* diff --git a/fs/fat/fat.c b/fs/fat/fat.c index 600a90e309..826bd85286 100644 --- a/fs/fat/fat.c +++ b/fs/fat/fat.c @@ -1254,7 +1254,7 @@ int file_fat_detectfs(void) #if defined(CONFIG_CMD_IDE) || \ defined(CONFIG_CMD_SATA) || \ - defined(CONFIG_CMD_SCSI) || \ + defined(CONFIG_SCSI) || \ defined(CONFIG_CMD_USB) || \ defined(CONFIG_MMC) printf("Interface: "); diff --git a/include/config_cmd_all.h b/include/config_cmd_all.h index ed502a191f..b5fd6c68e8 100644 --- a/include/config_cmd_all.h +++ b/include/config_cmd_all.h @@ -45,7 +45,7 @@ #define CONFIG_CMD_READ /* Read data from partition */ #define CONFIG_CMD_SANDBOX /* sb command to access sandbox features */ #define CONFIG_CMD_SAVES /* save S record dump */ -#define CONFIG_CMD_SCSI /* SCSI Support */ +#define CONFIG_SCSI /* SCSI Support */ #define CONFIG_CMD_SDRAM /* SDRAM DIMM SPD info printout */ #define CONFIG_CMD_TERMINAL /* built-in Serial Terminal */ #define CONFIG_CMD_UBI /* UBI Support */ diff --git a/include/config_distro_bootcmd.h b/include/config_distro_bootcmd.h index 7f673448c9..5a8d7f2708 100644 --- a/include/config_distro_bootcmd.h +++ b/include/config_distro_bootcmd.h @@ -165,7 +165,7 @@ BOOT_TARGET_DEVICES_references_SATA_without_CONFIG_CMD_SATA #endif -#ifdef CONFIG_CMD_SCSI +#ifdef CONFIG_SCSI #define BOOTENV_RUN_SCSI_INIT "run scsi_init; " #define BOOTENV_SET_SCSI_NEED_INIT "setenv scsi_need_init; " #define BOOTENV_SHARED_SCSI \ @@ -185,9 +185,9 @@ #define BOOTENV_SET_SCSI_NEED_INIT #define BOOTENV_SHARED_SCSI #define BOOTENV_DEV_SCSI \ - BOOT_TARGET_DEVICES_references_SCSI_without_CONFIG_CMD_SCSI + BOOT_TARGET_DEVICES_references_SCSI_without_CONFIG_SCSI #define BOOTENV_DEV_NAME_SCSI \ - BOOT_TARGET_DEVICES_references_SCSI_without_CONFIG_CMD_SCSI + BOOT_TARGET_DEVICES_references_SCSI_without_CONFIG_SCSI #endif #ifdef CONFIG_CMD_IDE diff --git a/include/config_fallbacks.h b/include/config_fallbacks.h index 2666191866..2ad54b7bf6 100644 --- a/include/config_fallbacks.h +++ b/include/config_fallbacks.h @@ -45,7 +45,7 @@ /* Rather than repeat this expression each time, add a define for it */ #if defined(CONFIG_CMD_IDE) || \ defined(CONFIG_CMD_SATA) || \ - defined(CONFIG_CMD_SCSI) || \ + defined(CONFIG_SCSI) || \ defined(CONFIG_CMD_USB) || \ defined(CONFIG_CMD_PART) || \ defined(CONFIG_CMD_GPT) || \ diff --git a/include/configs/MPC8544DS.h b/include/configs/MPC8544DS.h index 26d92daff1..f3036c1dc2 100644 --- a/include/configs/MPC8544DS.h +++ b/include/configs/MPC8544DS.h @@ -373,7 +373,7 @@ extern unsigned long get_board_sys_clk(unsigned long dummy); #if defined(CONFIG_PCI) #define CONFIG_CMD_PCI - #define CONFIG_CMD_SCSI + #define CONFIG_SCSI #endif /* diff --git a/include/configs/MPC8572DS.h b/include/configs/MPC8572DS.h index 8c4e5e21ca..bb7f38e34a 100644 --- a/include/configs/MPC8572DS.h +++ b/include/configs/MPC8572DS.h @@ -576,7 +576,7 @@ #if defined(CONFIG_PCI) #define CONFIG_CMD_PCI -#define CONFIG_CMD_SCSI +#define CONFIG_SCSI #endif /* diff --git a/include/configs/MPC8610HPCD.h b/include/configs/MPC8610HPCD.h index e7f01d00d1..f6d45a9e40 100644 --- a/include/configs/MPC8610HPCD.h +++ b/include/configs/MPC8610HPCD.h @@ -449,7 +449,7 @@ #if defined(CONFIG_PCI) #define CONFIG_CMD_PCI -#define CONFIG_CMD_SCSI +#define CONFIG_SCSI #endif #define CONFIG_WATCHDOG /* watchdog enabled */ diff --git a/include/configs/MPC8641HPCN.h b/include/configs/MPC8641HPCN.h index 5e23007d8d..9b2623c726 100644 --- a/include/configs/MPC8641HPCN.h +++ b/include/configs/MPC8641HPCN.h @@ -610,7 +610,7 @@ extern unsigned long get_board_sys_clk(unsigned long dummy); #if defined(CONFIG_PCI) #define CONFIG_CMD_PCI - #define CONFIG_CMD_SCSI + #define CONFIG_SCSI #endif #undef CONFIG_WATCHDOG /* watchdog disabled */ diff --git a/include/configs/PIP405.h b/include/configs/PIP405.h index 4bd06a45bf..4506d86eee 100644 --- a/include/configs/PIP405.h +++ b/include/configs/PIP405.h @@ -43,7 +43,7 @@ #define CONFIG_CMD_EEPROM #define CONFIG_CMD_REGINFO #define CONFIG_CMD_FDC -#define CONFIG_CMD_SCSI +#define CONFIG_SCSI #define CONFIG_CMD_DATE #define CONFIG_CMD_SDRAM #define CONFIG_CMD_SAVES diff --git a/include/configs/am57xx_evm.h b/include/configs/am57xx_evm.h index 32d7d4d0bd..d53b0fdd89 100644 --- a/include/configs/am57xx_evm.h +++ b/include/configs/am57xx_evm.h @@ -75,7 +75,7 @@ /* SATA */ #define CONFIG_BOARD_LATE_INIT -#define CONFIG_CMD_SCSI +#define CONFIG_SCSI #define CONFIG_LIBATA #define CONFIG_SCSI_AHCI #define CONFIG_SCSI_AHCI_PLAT diff --git a/include/configs/cm_t54.h b/include/configs/cm_t54.h index 9b13aa6b5a..ac6103c066 100644 --- a/include/configs/cm_t54.h +++ b/include/configs/cm_t54.h @@ -60,7 +60,7 @@ #define CONFIG_SPL_SATA_BOOT_DEVICE 0 #define CONFIG_SYS_SATA_FAT_BOOT_PARTITION 1 -#define CONFIG_CMD_SCSI +#define CONFIG_SCSI #define CONFIG_LIBATA #define CONFIG_SCSI_AHCI #define CONFIG_SCSI_AHCI_PLAT diff --git a/include/configs/db-88f6820-gp.h b/include/configs/db-88f6820-gp.h index d84dde39c1..3539a62790 100644 --- a/include/configs/db-88f6820-gp.h +++ b/include/configs/db-88f6820-gp.h @@ -27,7 +27,7 @@ #define CONFIG_SYS_NO_FLASH /* Declare no flash (NOR/SPI) */ #define CONFIG_CMD_ENV #define CONFIG_CMD_PCI -#define CONFIG_CMD_SCSI +#define CONFIG_SCSI /* I2C */ #define CONFIG_SYS_I2C diff --git a/include/configs/dra7xx_evm.h b/include/configs/dra7xx_evm.h index 79b6c09951..8a0cd66cd0 100644 --- a/include/configs/dra7xx_evm.h +++ b/include/configs/dra7xx_evm.h @@ -230,7 +230,7 @@ /* SATA */ #define CONFIG_BOARD_LATE_INIT -#define CONFIG_CMD_SCSI +#define CONFIG_SCSI #define CONFIG_LIBATA #define CONFIG_SCSI_AHCI #define CONFIG_SCSI_AHCI_PLAT diff --git a/include/configs/efi-x86.h b/include/configs/efi-x86.h index 6dd0b32dae..95e46c558d 100644 --- a/include/configs/efi-x86.h +++ b/include/configs/efi-x86.h @@ -18,7 +18,7 @@ #undef CONFIG_VIDEO #undef CONFIG_CFB_CONSOLE #undef CONFIG_SCSI_AHCI -#undef CONFIG_CMD_SCSI +#undef CONFIG_SCSI #undef CONFIG_INTEL_ICH6_GPIO #undef CONFIG_USB_EHCI_PCI diff --git a/include/configs/galileo.h b/include/configs/galileo.h index 2f1f6d4455..40f7fba833 100644 --- a/include/configs/galileo.h +++ b/include/configs/galileo.h @@ -29,7 +29,7 @@ /* SATA is not supported in Quark SoC */ #undef CONFIG_SCSI_AHCI -#undef CONFIG_CMD_SCSI +#undef CONFIG_SCSI /* Video is not supported in Quark SoC */ #undef CONFIG_VIDEO diff --git a/include/configs/highbank.h b/include/configs/highbank.h index 3bce12bbb8..5cefddc2e0 100644 --- a/include/configs/highbank.h +++ b/include/configs/highbank.h @@ -51,7 +51,7 @@ /* * Command line configuration. */ -#define CONFIG_CMD_SCSI +#define CONFIG_SCSI #define CONFIG_BOOT_RETRY_TIME -1 #define CONFIG_RESET_TO_RETRY diff --git a/include/configs/ls1043aqds.h b/include/configs/ls1043aqds.h index d71a229c61..af1f73dbaa 100644 --- a/include/configs/ls1043aqds.h +++ b/include/configs/ls1043aqds.h @@ -108,7 +108,7 @@ unsigned long get_board_ddr_clk(void); #define CONFIG_LIBATA #define CONFIG_SCSI_AHCI #define CONFIG_SCSI_AHCI_PLAT -#define CONFIG_CMD_SCSI +#define CONFIG_SCSI #define CONFIG_DOS_PARTITION #define CONFIG_BOARD_LATE_INIT diff --git a/include/configs/ls2080aqds.h b/include/configs/ls2080aqds.h index 2d7567f394..f8c9e51ae7 100644 --- a/include/configs/ls2080aqds.h +++ b/include/configs/ls2080aqds.h @@ -44,7 +44,7 @@ unsigned long get_board_ddr_clk(void); #define CONFIG_LIBATA #define CONFIG_SCSI_AHCI #define CONFIG_SCSI_AHCI_PLAT -#define CONFIG_CMD_SCSI +#define CONFIG_SCSI #define CONFIG_DOS_PARTITION #define CONFIG_BOARD_LATE_INIT diff --git a/include/configs/ls2080ardb.h b/include/configs/ls2080ardb.h index 5bec5099af..4577919ca1 100644 --- a/include/configs/ls2080ardb.h +++ b/include/configs/ls2080ardb.h @@ -62,7 +62,7 @@ unsigned long get_board_sys_clk(void); #define CONFIG_LIBATA #define CONFIG_SCSI_AHCI #define CONFIG_SCSI_AHCI_PLAT -#define CONFIG_CMD_SCSI +#define CONFIG_SCSI #define CONFIG_DOS_PARTITION #define CONFIG_BOARD_LATE_INIT diff --git a/include/configs/omap5_uevm.h b/include/configs/omap5_uevm.h index 86cefa3b8f..4ddc492112 100644 --- a/include/configs/omap5_uevm.h +++ b/include/configs/omap5_uevm.h @@ -115,7 +115,7 @@ /* Max time to hold reset on this board, see doc/README.omap-reset-time */ #define CONFIG_OMAP_PLATFORM_RESET_TIME_MAX_USEC 16296 -#define CONFIG_CMD_SCSI +#define CONFIG_SCSI #define CONFIG_LIBATA #define CONFIG_SCSI_AHCI #define CONFIG_SCSI_AHCI_PLAT diff --git a/include/configs/qemu-x86.h b/include/configs/qemu-x86.h index b0d2ffe5b4..476d37d4bc 100644 --- a/include/configs/qemu-x86.h +++ b/include/configs/qemu-x86.h @@ -43,7 +43,7 @@ #define CONFIG_ATAPI #undef CONFIG_SCSI_AHCI -#undef CONFIG_CMD_SCSI +#undef CONFIG_SCSI #else #define CONFIG_SCSI_DEV_LIST \ {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH9_AHCI} diff --git a/include/configs/sunxi-common.h b/include/configs/sunxi-common.h index 2406115e3e..ac2d93114b 100644 --- a/include/configs/sunxi-common.h +++ b/include/configs/sunxi-common.h @@ -125,7 +125,7 @@ #define CONFIG_SYS_SCSI_MAX_LUN 1 #define CONFIG_SYS_SCSI_MAX_DEVICE (CONFIG_SYS_SCSI_MAX_SCSI_ID * \ CONFIG_SYS_SCSI_MAX_LUN) -#define CONFIG_CMD_SCSI +#define CONFIG_SCSI #endif #define CONFIG_SETUP_MEMORY_TAGS diff --git a/include/configs/x86-common.h b/include/configs/x86-common.h index a2822e0114..b79f47baf3 100644 --- a/include/configs/x86-common.h +++ b/include/configs/x86-common.h @@ -100,7 +100,7 @@ #define CONFIG_CMD_IRQ #define CONFIG_CMD_PCI #define CONFIG_CMD_GETTIME -#define CONFIG_CMD_SCSI +#define CONFIG_SCSI #define CONFIG_CMD_ZBOOT diff --git a/include/configs/xilinx_zynqmp.h b/include/configs/xilinx_zynqmp.h index 060bca985e..6b8e3ea865 100644 --- a/include/configs/xilinx_zynqmp.h +++ b/include/configs/xilinx_zynqmp.h @@ -201,7 +201,7 @@ #define CONFIG_SYS_SCSI_MAX_LUN 1 #define CONFIG_SYS_SCSI_MAX_DEVICE (CONFIG_SYS_SCSI_MAX_SCSI_ID * \ CONFIG_SYS_SCSI_MAX_LUN) -#define CONFIG_CMD_SCSI +#define CONFIG_SCSI #endif #define CONFIG_SYS_BOOTM_LEN (60 * 1024 * 1024) From 6eef6eac1fc137c97bf1993304ed83b8e483c80a Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 1 May 2016 11:36:03 -0600 Subject: [PATCH 051/162] dm: blk: Add a legacy block interface There is quite a bit of duplicated common code related to block devices in the IDE and SCSI implementations. Create some helper functions that can be used to reduce the duplication. These rely on a linker list of interface-type drivers Signed-off-by: Simon Glass --- drivers/block/Makefile | 4 + drivers/block/blk_legacy.c | 261 +++++++++++++++++++++++++++++++++++++ include/blk.h | 195 +++++++++++++++++++++++++++ 3 files changed, 460 insertions(+) create mode 100644 drivers/block/blk_legacy.c diff --git a/drivers/block/Makefile b/drivers/block/Makefile index 3f759341d4..436b79f981 100644 --- a/drivers/block/Makefile +++ b/drivers/block/Makefile @@ -7,6 +7,10 @@ obj-$(CONFIG_BLK) += blk-uclass.o +ifndef CONFIG_BLK +obj-y += blk_legacy.o +endif + obj-$(CONFIG_AHCI) += ahci-uclass.o obj-$(CONFIG_SCSI_AHCI) += ahci.o obj-$(CONFIG_DWC_AHSATA) += dwc_ahsata.o diff --git a/drivers/block/blk_legacy.c b/drivers/block/blk_legacy.c new file mode 100644 index 0000000000..7b90a8a6e1 --- /dev/null +++ b/drivers/block/blk_legacy.c @@ -0,0 +1,261 @@ +/* + * Copyright (C) 2016 Google, Inc + * Written by Simon Glass + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include + +struct blk_driver *blk_driver_lookup_type(int if_type) +{ + struct blk_driver *drv = ll_entry_start(struct blk_driver, blk_driver); + const int n_ents = ll_entry_count(struct blk_driver, blk_driver); + struct blk_driver *entry; + + for (entry = drv; entry != drv + n_ents; entry++) { + if (if_type == entry->if_type) + return entry; + } + + /* Not found */ + return NULL; +} + +static struct blk_driver *blk_driver_lookup_typename(const char *if_typename) +{ + struct blk_driver *drv = ll_entry_start(struct blk_driver, blk_driver); + const int n_ents = ll_entry_count(struct blk_driver, blk_driver); + struct blk_driver *entry; + + for (entry = drv; entry != drv + n_ents; entry++) { + if (!strcmp(if_typename, entry->if_typename)) + return entry; + } + + /* Not found */ + return NULL; +} + +/** + * get_desc() - Get the block device descriptor for the given device number + * + * @drv: Legacy block driver + * @devnum: Device number (0 = first) + * @descp: Returns block device descriptor on success + * @return 0 on success, -ENODEV if there is no such device, -ENOSYS if the + * driver does not provide a way to find a device, or other -ve on other + * error. + */ +static int get_desc(struct blk_driver *drv, int devnum, struct blk_desc **descp) +{ + if (drv->desc) { + if (devnum < 0 || devnum >= drv->max_devs) + return -ENODEV; + *descp = &drv->desc[devnum]; + return 0; + } + if (!drv->get_dev) + return -ENOSYS; + + return drv->get_dev(devnum, descp); +} + +#ifdef HAVE_BLOCK_DEVICE +int blk_list_part(enum if_type if_type) +{ + struct blk_driver *drv; + struct blk_desc *desc; + int devnum, ok; + bool first = true; + + drv = blk_driver_lookup_type(if_type); + if (!drv) + return -ENOSYS; + for (ok = 0, devnum = 0; devnum < drv->max_devs; ++devnum) { + if (get_desc(drv, devnum, &desc)) + continue; + if (desc->part_type != PART_TYPE_UNKNOWN) { + ++ok; + if (!first) + putc('\n'); + part_print(desc); + first = false; + } + } + if (!ok) + return -ENODEV; + + return 0; +} + +int blk_print_part_devnum(enum if_type if_type, int devnum) +{ + struct blk_driver *drv = blk_driver_lookup_type(if_type); + struct blk_desc *desc; + int ret; + + if (!drv) + return -ENOSYS; + ret = get_desc(drv, devnum, &desc); + if (ret) + return ret; + if (desc->type == DEV_TYPE_UNKNOWN) + return -ENOENT; + part_print(desc); + + return 0; +} + +void blk_list_devices(enum if_type if_type) +{ + struct blk_driver *drv = blk_driver_lookup_type(if_type); + struct blk_desc *desc; + int i; + + if (!drv) + return; + for (i = 0; i < drv->max_devs; ++i) { + if (get_desc(drv, i, &desc)) + continue; + if (desc->type == DEV_TYPE_UNKNOWN) + continue; /* list only known devices */ + printf("Device %d: ", i); + dev_print(desc); + } +} + +int blk_print_device_num(enum if_type if_type, int devnum) +{ + struct blk_driver *drv = blk_driver_lookup_type(if_type); + struct blk_desc *desc; + int ret; + + if (!drv) + return -ENOSYS; + ret = get_desc(drv, devnum, &desc); + if (ret) + return ret; + printf("\n%s device %d: ", drv->if_typename, devnum); + dev_print(desc); + + return 0; +} + +int blk_show_device(enum if_type if_type, int devnum) +{ + struct blk_driver *drv = blk_driver_lookup_type(if_type); + struct blk_desc *desc; + int ret; + + if (!drv) + return -ENOSYS; + printf("\nDevice %d: ", devnum); + if (devnum >= drv->max_devs) { + puts("unknown device\n"); + return -ENODEV; + } + ret = get_desc(drv, devnum, &desc); + if (ret) + return ret; + dev_print(desc); + + if (desc->type == DEV_TYPE_UNKNOWN) + return -ENOENT; + + return 0; +} +#endif /* HAVE_BLOCK_DEVICE */ + +struct blk_desc *blk_get_devnum_by_type(enum if_type if_type, int devnum) +{ + struct blk_driver *drv = blk_driver_lookup_type(if_type); + struct blk_desc *desc; + + if (!drv) + return NULL; + + if (get_desc(drv, devnum, &desc)) + return NULL; + + return desc; +} + +int blk_dselect_hwpart(struct blk_desc *desc, int hwpart) +{ + struct blk_driver *drv = blk_driver_lookup_type(desc->if_type); + + if (!drv) + return -ENOSYS; + if (drv->select_hwpart) + return drv->select_hwpart(desc, hwpart); + + return 0; +} + +struct blk_desc *blk_get_devnum_by_typename(const char *if_typename, int devnum) +{ + struct blk_driver *drv = blk_driver_lookup_typename(if_typename); + struct blk_desc *desc; + + if (!drv) + return NULL; + + if (get_desc(drv, devnum, &desc)) + return NULL; + + return desc; +} + +ulong blk_read_devnum(enum if_type if_type, int devnum, lbaint_t start, + lbaint_t blkcnt, void *buffer) +{ + struct blk_driver *drv = blk_driver_lookup_type(if_type); + struct blk_desc *desc; + ulong n; + int ret; + + if (!drv) + return -ENOSYS; + ret = get_desc(drv, devnum, &desc); + if (ret) + return ret; + n = desc->block_read(desc, start, blkcnt, buffer); + if (IS_ERR_VALUE(n)) + return n; + + /* flush cache after read */ + flush_cache((ulong)buffer, blkcnt * desc->blksz); + + return n; +} + +ulong blk_write_devnum(enum if_type if_type, int devnum, lbaint_t start, + lbaint_t blkcnt, const void *buffer) +{ + struct blk_driver *drv = blk_driver_lookup_type(if_type); + struct blk_desc *desc; + int ret; + + if (!drv) + return -ENOSYS; + ret = get_desc(drv, devnum, &desc); + if (ret) + return ret; + return desc->block_write(desc, start, blkcnt, buffer); +} + +int blk_select_hwpart_devnum(enum if_type if_type, int devnum, int hwpart) +{ + struct blk_driver *drv = blk_driver_lookup_type(if_type); + struct blk_desc *desc; + int ret; + + if (!drv) + return -ENOSYS; + ret = get_desc(drv, devnum, &desc); + if (ret) + return ret; + return drv->select_hwpart(desc, hwpart); +} diff --git a/include/blk.h b/include/blk.h index f62467105a..a562c10a29 100644 --- a/include/blk.h +++ b/include/blk.h @@ -340,6 +340,201 @@ static inline ulong blk_derase(struct blk_desc *block_dev, lbaint_t start, blkcache_invalidate(block_dev->if_type, block_dev->devnum); return block_dev->block_erase(block_dev, start, blkcnt); } + +/** + * struct blk_driver - Driver for block interface types + * + * This provides access to the block devices for each interface type. One + * driver should be provided using U_BOOT_LEGACY_BLK() for each interface + * type that is to be supported. + * + * @if_typename: Interface type name + * @if_type: Interface type + * @max_devs: Maximum number of devices supported + * @desc: Pointer to list of devices for this interface type, + * or NULL to use @get_dev() instead + */ +struct blk_driver { + const char *if_typename; + enum if_type if_type; + int max_devs; + struct blk_desc *desc; + /** + * get_dev() - get a pointer to a block device given its number + * + * Each interface allocates its own devices and typically + * struct blk_desc is contained with the interface's data structure. + * There is no global numbering for block devices. This method allows + * the device for an interface type to be obtained when @desc is NULL. + * + * @devnum: Device number (0 for first device on that interface, + * 1 for second, etc. + * @descp: Returns pointer to the block device on success + * @return 0 if OK, -ve on error + */ + int (*get_dev)(int devnum, struct blk_desc **descp); + + /** + * select_hwpart() - Select a hardware partition + * + * Some devices (e.g. MMC) can support partitioning at the hardware + * level. This is quite separate from the normal idea of + * software-based partitions. MMC hardware partitions must be + * explicitly selected. Once selected only the region of the device + * covered by that partition is accessible. + * + * The MMC standard provides for two boot partitions (numbered 1 and 2), + * rpmb (3), and up to 4 addition general-purpose partitions (4-7). + * Partition 0 is the main user-data partition. + * + * @desc: Block device descriptor + * @hwpart: Hardware partition number to select. 0 means the main + * user-data partition, 1 is the first partition, 2 is + * the second, etc. + * @return 0 if OK, other value for an error + */ + int (*select_hwpart)(struct blk_desc *desc, int hwpart); +}; + +/* + * Declare a new U-Boot legacy block driver. New drivers should use driver + * model (UCLASS_BLK). + */ +#define U_BOOT_LEGACY_BLK(__name) \ + ll_entry_declare(struct blk_driver, __name, blk_driver) + +struct blk_driver *blk_driver_lookup_type(int if_type); + #endif /* !CONFIG_BLK */ +/** + * blk_get_devnum_by_typename() - Get a block device by type and number + * + * This looks through the available block devices of the given type, returning + * the one with the given @devnum. + * + * @if_type: Block device type + * @devnum: Device number + * @return point to block device descriptor, or NULL if not found + */ +struct blk_desc *blk_get_devnum_by_type(enum if_type if_type, int devnum); + +/** + * blk_get_devnum_by_type() - Get a block device by type name, and number + * + * This looks up the block device type based on @if_typename, then calls + * blk_get_devnum_by_type(). + * + * @if_typename: Block device type name + * @devnum: Device number + * @return point to block device descriptor, or NULL if not found + */ +struct blk_desc *blk_get_devnum_by_typename(const char *if_typename, + int devnum); + +/** + * blk_dselect_hwpart() - select a hardware partition + * + * This selects a hardware partition (such as is supported by MMC). The block + * device size may change as this effectively points the block device to a + * partition at the hardware level. See the select_hwpart() method above. + * + * @desc: Block device descriptor for the device to select + * @hwpart: Partition number to select + * @return 0 if OK, -ve on error + */ +int blk_dselect_hwpart(struct blk_desc *desc, int hwpart); + +/** + * blk_list_part() - list the partitions for block devices of a given type + * + * This looks up the partition type for each block device of type @if_type, + * then displays a list of partitions. + * + * @if_type: Block device type + * @return 0 if OK, -ENODEV if there is none of that type + */ +int blk_list_part(enum if_type if_type); + +/** + * blk_list_devices() - list the block devices of a given type + * + * This lists each block device of the type @if_type, showing the capacity + * as well as type-specific information. + * + * @if_type: Block device type + */ +void blk_list_devices(enum if_type if_type); + +/** + * blk_show_device() - show information about a given block device + * + * This shows the block device capacity as well as type-specific information. + * + * @if_type: Block device type + * @devnum: Device number + * @return 0 if OK, -ENODEV for invalid device number + */ +int blk_show_device(enum if_type if_type, int devnum); + +/** + * blk_print_device_num() - show information about a given block device + * + * This is similar to blk_show_device() but returns an error if the block + * device type is unknown. + * + * @if_type: Block device type + * @devnum: Device number + * @return 0 if OK, -ENODEV for invalid device number, -ENOENT if the block + * device is not connected + */ +int blk_print_device_num(enum if_type if_type, int devnum); + +/** + * blk_print_part_devnum() - print the partition information for a device + * + * @if_type: Block device type + * @devnum: Device number + * @return 0 if OK, -ENOENT if the block device is not connected, -ENOSYS if + * the interface type is not supported, other -ve on other error + */ +int blk_print_part_devnum(enum if_type if_type, int devnum); + +/** + * blk_read_devnum() - read blocks from a device + * + * @if_type: Block device type + * @devnum: Device number + * @blkcnt: Number of blocks to read + * @buffer: Address to write data to + * @return number of blocks read, or -ve error number on error + */ +ulong blk_read_devnum(enum if_type if_type, int devnum, lbaint_t start, + lbaint_t blkcnt, void *buffer); + +/** + * blk_write_devnum() - write blocks to a device + * + * @if_type: Block device type + * @devnum: Device number + * @blkcnt: Number of blocks to write + * @buffer: Address to read data from + * @return number of blocks written, or -ve error number on error + */ +ulong blk_write_devnum(enum if_type if_type, int devnum, lbaint_t start, + lbaint_t blkcnt, const void *buffer); + +/** + * blk_select_hwpart_devnum() - select a hardware partition + * + * This is similar to blk_dselect_hwpart() but it looks up the interface and + * device number. + * + * @if_type: Block device type + * @devnum: Device number + * @hwpart: Partition number to select + * @return 0 if OK, -ve on error + */ +int blk_select_hwpart_devnum(enum if_type if_type, int devnum, int hwpart); + #endif From 3ef85e377201c1ebe84e74bfb785c95ccbc37b13 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 1 May 2016 11:36:04 -0600 Subject: [PATCH 052/162] dm: systemace: Add a legacy block interface Add a legacy block interface for systemace. Signed-off-by: Simon Glass --- drivers/block/systemace.c | 14 ++++++++++++++ include/blk.h | 1 + 2 files changed, 15 insertions(+) diff --git a/drivers/block/systemace.c b/drivers/block/systemace.c index 09fe834e22..0d8e26f8aa 100644 --- a/drivers/block/systemace.c +++ b/drivers/block/systemace.c @@ -132,6 +132,13 @@ struct blk_desc *systemace_get_dev(int dev) } #endif +static int systemace_get_devp(int dev, struct blk_desc **descp) +{ + *descp = systemace_get_dev(dev); + + return 0; +} + /* * This function is called (by dereferencing the block_read pointer in * the dev_desc) to read blocks of data. The return value is the @@ -257,3 +264,10 @@ static unsigned long systemace_read(struct blk_desc *block_dev, return blkcnt; } + +U_BOOT_LEGACY_BLK(systemace) = { + .if_typename = "ace", + .if_type = IF_TYPE_SYSTEMACE, + .max_devs = 1, + .get_dev = systemace_get_devp, +}; diff --git a/include/blk.h b/include/blk.h index a562c10a29..2caac9c96b 100644 --- a/include/blk.h +++ b/include/blk.h @@ -30,6 +30,7 @@ enum if_type { IF_TYPE_SD, IF_TYPE_SATA, IF_TYPE_HOST, + IF_TYPE_SYSTEMACE, IF_TYPE_COUNT, /* Number of interface types */ }; From 0cc65a7cc23bfbaab709d8934a6b8c73084852ea Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 1 May 2016 11:36:05 -0600 Subject: [PATCH 053/162] dm: sandbox: Add a legacy host block interface Add a legacy block interface for sandbox host. Signed-off-by: Simon Glass --- drivers/block/sandbox.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/block/sandbox.c b/drivers/block/sandbox.c index 6d41508d5c..2b6a89333b 100644 --- a/drivers/block/sandbox.c +++ b/drivers/block/sandbox.c @@ -239,4 +239,11 @@ U_BOOT_DRIVER(sandbox_host_blk) = { .ops = &sandbox_host_blk_ops, .priv_auto_alloc_size = sizeof(struct host_block_dev), }; +#else +U_BOOT_LEGACY_BLK(sandbox_host) = { + .if_typename = "host", + .if_type = IF_TYPE_HOST, + .max_devs = CONFIG_HOST_MAX_DEVICES, + .get_dev = host_get_dev_err, +}; #endif From c0543bf6be4bac277d65c601f9150c7faf3d125e Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 1 May 2016 11:36:06 -0600 Subject: [PATCH 054/162] dm: usb: Add a legacy block interface for USB storage Add a legacy block interface for USB storage. Signed-off-by: Simon Glass --- common/usb_storage.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/common/usb_storage.c b/common/usb_storage.c index 9285c95c05..80bf3db5d0 100644 --- a/common/usb_storage.c +++ b/common/usb_storage.c @@ -1555,4 +1555,11 @@ U_BOOT_DRIVER(usb_storage_blk) = { .id = UCLASS_BLK, .ops = &usb_storage_ops, }; +#else +U_BOOT_LEGACY_BLK(usb) = { + .if_typename = "usb", + .if_type = IF_TYPE_USB, + .max_devs = USB_MAX_STOR_DEV, + .desc = usb_dev_desc, +}; #endif From 663acabdc548216d61a9d2b1f789d4e6606f7a52 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 1 May 2016 11:36:07 -0600 Subject: [PATCH 055/162] dm: mmc: Add a legacy block interface for MMC Add a legacy block interface for MMC. Signed-off-by: Simon Glass --- drivers/mmc/mmc.c | 30 +++++++++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c index d3c22abfd5..024368c727 100644 --- a/drivers/mmc/mmc.c +++ b/drivers/mmc/mmc.c @@ -1582,14 +1582,31 @@ void mmc_destroy(struct mmc *mmc) free(mmc); } +static int mmc_get_devp(int dev, struct blk_desc **descp) +{ + struct mmc *mmc = find_mmc_device(dev); + int ret; + + if (!mmc) + return -ENODEV; + ret = mmc_init(mmc); + if (ret) + return ret; + + *descp = &mmc->block_dev; + + return 0; +} + #ifdef CONFIG_PARTITIONS struct blk_desc *mmc_get_dev(int dev) { - struct mmc *mmc = find_mmc_device(dev); - if (!mmc || mmc_init(mmc)) + struct blk_desc *desc; + + if (mmc_get_devp(dev, &desc)) return NULL; - return &mmc->block_dev; + return desc; } #endif @@ -1965,3 +1982,10 @@ int mmc_set_rst_n_function(struct mmc *mmc, u8 enable) enable); } #endif + +U_BOOT_LEGACY_BLK(mmc) = { + .if_typename = "mmc", + .if_type = IF_TYPE_MMC, + .max_devs = -1, + .get_dev = mmc_get_devp, +}; From d508c82ba90dd92fa3b70875d3419c9d1b5493c0 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 1 May 2016 11:36:08 -0600 Subject: [PATCH 056/162] dm: mmc: Add an implementation of the 'devnum' functions Now that the MMC code accesses devices by number, we can implement this same interface for driver model, allowing MMC to support using driver model for block devices. Add the required functions to the uclass. Signed-off-by: Simon Glass --- drivers/block/blk-uclass.c | 280 +++++++++++++++++++++++++++++++++++++ 1 file changed, 280 insertions(+) diff --git a/drivers/block/blk-uclass.c b/drivers/block/blk-uclass.c index 617db226a2..3687b9a100 100644 --- a/drivers/block/blk-uclass.c +++ b/drivers/block/blk-uclass.c @@ -11,6 +11,286 @@ #include #include +static const char *if_typename_str[IF_TYPE_COUNT] = { + [IF_TYPE_IDE] = "ide", + [IF_TYPE_SCSI] = "scsi", + [IF_TYPE_ATAPI] = "atapi", + [IF_TYPE_USB] = "usb", + [IF_TYPE_DOC] = "doc", + [IF_TYPE_MMC] = "mmc", + [IF_TYPE_SD] = "sd", + [IF_TYPE_SATA] = "sata", + [IF_TYPE_HOST] = "host", + [IF_TYPE_SYSTEMACE] = "ace", +}; + +static enum uclass_id if_type_uclass_id[IF_TYPE_COUNT] = { + [IF_TYPE_IDE] = UCLASS_INVALID, + [IF_TYPE_SCSI] = UCLASS_INVALID, + [IF_TYPE_ATAPI] = UCLASS_INVALID, + [IF_TYPE_USB] = UCLASS_MASS_STORAGE, + [IF_TYPE_DOC] = UCLASS_INVALID, + [IF_TYPE_MMC] = UCLASS_MMC, + [IF_TYPE_SD] = UCLASS_INVALID, + [IF_TYPE_SATA] = UCLASS_AHCI, + [IF_TYPE_HOST] = UCLASS_ROOT, + [IF_TYPE_SYSTEMACE] = UCLASS_INVALID, +}; + +static enum if_type if_typename_to_iftype(const char *if_typename) +{ + int i; + + for (i = 0; i < IF_TYPE_COUNT; i++) { + if (if_typename_str[i] && + !strcmp(if_typename, if_typename_str[i])) + return i; + } + + return IF_TYPE_UNKNOWN; +} + +static enum uclass_id if_type_to_uclass_id(enum if_type if_type) +{ + return if_type_uclass_id[if_type]; +} + +struct blk_desc *blk_get_devnum_by_type(enum if_type if_type, int devnum) +{ + struct blk_desc *desc; + struct udevice *dev; + int ret; + + ret = blk_get_device(if_type, devnum, &dev); + if (ret) + return NULL; + desc = dev_get_uclass_platdata(dev); + + return desc; +} + +/* + * This function is complicated with driver model. We look up the interface + * name in a local table. This gives us an interface type which we can match + * against the uclass of the block device's parent. + */ +struct blk_desc *blk_get_devnum_by_typename(const char *if_typename, int devnum) +{ + enum uclass_id uclass_id; + enum if_type if_type; + struct udevice *dev; + struct uclass *uc; + int ret; + + if_type = if_typename_to_iftype(if_typename); + if (if_type == IF_TYPE_UNKNOWN) { + debug("%s: Unknown interface type '%s'\n", __func__, + if_typename); + return NULL; + } + uclass_id = if_type_to_uclass_id(if_type); + if (uclass_id == UCLASS_INVALID) { + debug("%s: Unknown uclass for interface type'\n", + if_typename_str[if_type]); + return NULL; + } + + ret = uclass_get(UCLASS_BLK, &uc); + if (ret) + return NULL; + uclass_foreach_dev(dev, uc) { + struct blk_desc *desc = dev_get_uclass_platdata(dev); + + debug("%s: if_type=%d, devnum=%d: %s, %d, %d\n", __func__, + if_type, devnum, dev->name, desc->if_type, desc->devnum); + if (desc->devnum != devnum) + continue; + + /* Find out the parent device uclass */ + if (device_get_uclass_id(dev->parent) != uclass_id) { + debug("%s: parent uclass %d, this dev %d\n", __func__, + device_get_uclass_id(dev->parent), uclass_id); + continue; + } + + if (device_probe(dev)) + return NULL; + + debug("%s: Device desc %p\n", __func__, desc); + return desc; + } + debug("%s: No device found\n", __func__); + + return NULL; +} + +/** + * get_desc() - Get the block device descriptor for the given device number + * + * @if_type: Interface type + * @devnum: Device number (0 = first) + * @descp: Returns block device descriptor on success + * @return 0 on success, -ENODEV if there is no such device and no device + * with a higher device number, -ENOENT if there is no such device but there + * is one with a higher number, or other -ve on other error. + */ +static int get_desc(enum if_type if_type, int devnum, struct blk_desc **descp) +{ + bool found_more = false; + struct udevice *dev; + struct uclass *uc; + int ret; + + *descp = NULL; + ret = uclass_get(UCLASS_BLK, &uc); + if (ret) + return ret; + uclass_foreach_dev(dev, uc) { + struct blk_desc *desc = dev_get_uclass_platdata(dev); + + debug("%s: if_type=%d, devnum=%d: %s, %d, %d\n", __func__, + if_type, devnum, dev->name, desc->if_type, desc->devnum); + if (desc->if_type == if_type) { + if (desc->devnum == devnum) { + ret = device_probe(dev); + if (ret) + return ret; + + } else if (desc->devnum > devnum) { + found_more = true; + } + } + } + + return found_more ? -ENOENT : -ENODEV; +} + +int blk_list_part(enum if_type if_type) +{ + struct blk_desc *desc; + int devnum, ok; + int ret; + + for (ok = 0, devnum = 0;; ++devnum) { + ret = get_desc(if_type, devnum, &desc); + if (ret == -ENODEV) + break; + else if (ret) + continue; + if (desc->part_type != PART_TYPE_UNKNOWN) { + ++ok; + if (devnum) + putc('\n'); + part_print(desc); + } + } + if (!ok) + return -ENODEV; + + return 0; +} + +int blk_print_part_devnum(enum if_type if_type, int devnum) +{ + struct blk_desc *desc; + int ret; + + ret = get_desc(if_type, devnum, &desc); + if (ret) + return ret; + if (desc->type == DEV_TYPE_UNKNOWN) + return -ENOENT; + part_print(desc); + + return 0; +} + +void blk_list_devices(enum if_type if_type) +{ + struct blk_desc *desc; + int ret; + int i; + + for (i = 0;; ++i) { + ret = get_desc(if_type, i, &desc); + if (ret == -ENODEV) + break; + else if (ret) + continue; + if (desc->type == DEV_TYPE_UNKNOWN) + continue; /* list only known devices */ + printf("Device %d: ", i); + dev_print(desc); + } +} + +int blk_print_device_num(enum if_type if_type, int devnum) +{ + struct blk_desc *desc; + int ret; + + ret = get_desc(if_type, devnum, &desc); + if (ret) + return ret; + printf("\nIDE device %d: ", devnum); + dev_print(desc); + + return 0; +} + +int blk_show_device(enum if_type if_type, int devnum) +{ + struct blk_desc *desc; + int ret; + + printf("\nDevice %d: ", devnum); + ret = get_desc(if_type, devnum, &desc); + if (ret == -ENODEV || ret == -ENOENT) { + printf("unknown device\n"); + return -ENODEV; + } + if (ret) + return ret; + dev_print(desc); + + if (desc->type == DEV_TYPE_UNKNOWN) + return -ENOENT; + + return 0; +} + +ulong blk_read_devnum(enum if_type if_type, int devnum, lbaint_t start, + lbaint_t blkcnt, void *buffer) +{ + struct blk_desc *desc; + ulong n; + int ret; + + ret = get_desc(if_type, devnum, &desc); + if (ret) + return ret; + n = blk_dread(desc, start, blkcnt, buffer); + if (IS_ERR_VALUE(n)) + return n; + + /* flush cache after read */ + flush_cache((ulong)buffer, blkcnt * desc->blksz); + + return n; +} + +ulong blk_write_devnum(enum if_type if_type, int devnum, lbaint_t start, + lbaint_t blkcnt, const void *buffer) +{ + struct blk_desc *desc; + int ret; + + ret = get_desc(if_type, devnum, &desc); + if (ret) + return ret; + return blk_dwrite(desc, start, blkcnt, buffer); +} + int blk_first_device(int if_type, struct udevice **devp) { struct blk_desc *desc; From 11f610edf01abc96ca10e82e1752648ee911705b Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 1 May 2016 11:36:09 -0600 Subject: [PATCH 057/162] dm: scsi: Separate the non-command code into its own file At present the SCSI command code includes both the command-processing code and the core SCSI functions and data structures. Separate the latter into its own file, adding functions as needed to avoid the command code accessing data structures directly. This functions use the new legacy block functions. With this commit: - There is no CONFIG option referenced from the command code - The concept of a 'current SCSI device' is confined to the command code This will make it easier to convert this code to driver model. Signed-off-by: Simon Glass --- cmd/Makefile | 6 - cmd/scsi.c | 626 +++--------------------------------------------- common/Makefile | 4 + common/scsi.c | 567 +++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 600 insertions(+), 603 deletions(-) create mode 100644 common/scsi.c diff --git a/cmd/Makefile b/cmd/Makefile index 6612a3b2b5..e3e0c74ffc 100644 --- a/cmd/Makefile +++ b/cmd/Makefile @@ -155,12 +155,6 @@ obj-$(CONFIG_CMD_PMIC) += pmic.o obj-$(CONFIG_CMD_REGULATOR) += regulator.o endif # !CONFIG_SPL_BUILD -ifdef CONFIG_SPL_BUILD -ifdef CONFIG_SPL_SATA_SUPPORT -obj-$(CONFIG_SCSI) += scsi.o -endif -endif # CONFIG_SPL_BUILD - obj-$(CONFIG_CMD_BLOB) += blob.o # core command diff --git a/cmd/scsi.c b/cmd/scsi.c index 751fc5818a..387ca1a262 100644 --- a/cmd/scsi.c +++ b/cmd/scsi.c @@ -10,355 +10,27 @@ */ #include #include -#include -#include #include -#include -#include - -#ifdef CONFIG_SCSI_DEV_LIST -#define SCSI_DEV_LIST CONFIG_SCSI_DEV_LIST -#else -#ifdef CONFIG_SCSI_SYM53C8XX -#define SCSI_VEND_ID 0x1000 -#ifndef CONFIG_SCSI_DEV_ID -#define SCSI_DEV_ID 0x0001 -#else -#define SCSI_DEV_ID CONFIG_SCSI_DEV_ID -#endif -#elif defined CONFIG_SATA_ULI5288 - -#define SCSI_VEND_ID 0x10b9 -#define SCSI_DEV_ID 0x5288 - -#elif !defined(CONFIG_SCSI_AHCI_PLAT) -#error no scsi device defined -#endif -#define SCSI_DEV_LIST {SCSI_VEND_ID, SCSI_DEV_ID} -#endif - -#if defined(CONFIG_PCI) && !defined(CONFIG_SCSI_AHCI_PLAT) -const struct pci_device_id scsi_device_list[] = { SCSI_DEV_LIST }; -#endif -static ccb tempccb; /* temporary scsi command buffer */ - -static unsigned char tempbuff[512]; /* temporary data buffer */ - -static int scsi_max_devs; /* number of highest available scsi device */ static int scsi_curr_dev; /* current device */ -static struct blk_desc scsi_dev_desc[CONFIG_SYS_SCSI_MAX_DEVICE]; - -/* almost the maximum amount of the scsi_ext command.. */ -#define SCSI_MAX_READ_BLK 0xFFFF -#define SCSI_LBA48_READ 0xFFFFFFF - -#ifdef CONFIG_SYS_64BIT_LBA -void scsi_setup_read16(ccb *pccb, lbaint_t start, unsigned long blocks) -{ - pccb->cmd[0] = SCSI_READ16; - pccb->cmd[1] = pccb->lun << 5; - pccb->cmd[2] = (unsigned char)(start >> 56) & 0xff; - pccb->cmd[3] = (unsigned char)(start >> 48) & 0xff; - pccb->cmd[4] = (unsigned char)(start >> 40) & 0xff; - pccb->cmd[5] = (unsigned char)(start >> 32) & 0xff; - pccb->cmd[6] = (unsigned char)(start >> 24) & 0xff; - pccb->cmd[7] = (unsigned char)(start >> 16) & 0xff; - pccb->cmd[8] = (unsigned char)(start >> 8) & 0xff; - pccb->cmd[9] = (unsigned char)start & 0xff; - pccb->cmd[10] = 0; - pccb->cmd[11] = (unsigned char)(blocks >> 24) & 0xff; - pccb->cmd[12] = (unsigned char)(blocks >> 16) & 0xff; - pccb->cmd[13] = (unsigned char)(blocks >> 8) & 0xff; - pccb->cmd[14] = (unsigned char)blocks & 0xff; - pccb->cmd[15] = 0; - pccb->cmdlen = 16; - pccb->msgout[0] = SCSI_IDENTIFY; /* NOT USED */ - debug("scsi_setup_read16: cmd: %02X %02X startblk %02X%02X%02X%02X%02X%02X%02X%02X blccnt %02X%02X%02X%02X\n", - pccb->cmd[0], pccb->cmd[1], - pccb->cmd[2], pccb->cmd[3], pccb->cmd[4], pccb->cmd[5], - pccb->cmd[6], pccb->cmd[7], pccb->cmd[8], pccb->cmd[9], - pccb->cmd[11], pccb->cmd[12], pccb->cmd[13], pccb->cmd[14]); -} -#endif - -void scsi_setup_read_ext(ccb * pccb, lbaint_t start, unsigned short blocks) -{ - pccb->cmd[0] = SCSI_READ10; - pccb->cmd[1] = pccb->lun << 5; - pccb->cmd[2] = (unsigned char)(start >> 24) & 0xff; - pccb->cmd[3] = (unsigned char)(start >> 16) & 0xff; - pccb->cmd[4] = (unsigned char)(start >> 8) & 0xff; - pccb->cmd[5] = (unsigned char)start & 0xff; - pccb->cmd[6] = 0; - pccb->cmd[7] = (unsigned char)(blocks >> 8) & 0xff; - pccb->cmd[8] = (unsigned char)blocks & 0xff; - pccb->cmd[6] = 0; - pccb->cmdlen=10; - pccb->msgout[0] = SCSI_IDENTIFY; /* NOT USED */ - debug ("scsi_setup_read_ext: cmd: %02X %02X startblk %02X%02X%02X%02X blccnt %02X%02X\n", - pccb->cmd[0],pccb->cmd[1], - pccb->cmd[2],pccb->cmd[3],pccb->cmd[4],pccb->cmd[5], - pccb->cmd[7],pccb->cmd[8]); -} - -void scsi_setup_write_ext(ccb *pccb, lbaint_t start, unsigned short blocks) -{ - pccb->cmd[0] = SCSI_WRITE10; - pccb->cmd[1] = pccb->lun << 5; - pccb->cmd[2] = (unsigned char)(start >> 24) & 0xff; - pccb->cmd[3] = (unsigned char)(start >> 16) & 0xff; - pccb->cmd[4] = (unsigned char)(start >> 8) & 0xff; - pccb->cmd[5] = (unsigned char)start & 0xff; - pccb->cmd[6] = 0; - pccb->cmd[7] = ((unsigned char)(blocks >> 8)) & 0xff; - pccb->cmd[8] = (unsigned char)blocks & 0xff; - pccb->cmd[9] = 0; - pccb->cmdlen = 10; - pccb->msgout[0] = SCSI_IDENTIFY; /* NOT USED */ - debug("%s: cmd: %02X %02X startblk %02X%02X%02X%02X blccnt %02X%02X\n", - __func__, - pccb->cmd[0], pccb->cmd[1], - pccb->cmd[2], pccb->cmd[3], pccb->cmd[4], pccb->cmd[5], - pccb->cmd[7], pccb->cmd[8]); -} - -void scsi_setup_read6(ccb * pccb, lbaint_t start, unsigned short blocks) -{ - pccb->cmd[0] = SCSI_READ6; - pccb->cmd[1] = pccb->lun << 5 | ((unsigned char)(start >> 16) & 0x1f); - pccb->cmd[2] = (unsigned char)(start >> 8) & 0xff; - pccb->cmd[3] = (unsigned char)start & 0xff; - pccb->cmd[4] = (unsigned char)blocks & 0xff; - pccb->cmd[5] = 0; - pccb->cmdlen=6; - pccb->msgout[0] = SCSI_IDENTIFY; /* NOT USED */ - debug("scsi_setup_read6: cmd: %02X %02X startblk %02X%02X blccnt %02X\n", - pccb->cmd[0], pccb->cmd[1], - pccb->cmd[2], pccb->cmd[3], pccb->cmd[4]); -} - - -void scsi_setup_inquiry(ccb * pccb) -{ - pccb->cmd[0] = SCSI_INQUIRY; - pccb->cmd[1] = pccb->lun << 5; - pccb->cmd[2] = 0; - pccb->cmd[3] = 0; - if (pccb->datalen > 255) - pccb->cmd[4] = 255; - else - pccb->cmd[4] = (unsigned char)pccb->datalen; - pccb->cmd[5] = 0; - pccb->cmdlen=6; - pccb->msgout[0] = SCSI_IDENTIFY; /* NOT USED */ -} - -static ulong scsi_read(struct blk_desc *block_dev, lbaint_t blknr, - lbaint_t blkcnt, void *buffer) -{ - int device = block_dev->devnum; - lbaint_t start, blks; - uintptr_t buf_addr; - unsigned short smallblks = 0; - ccb* pccb=(ccb *)&tempccb; - device&=0xff; - - /* Setup device */ - pccb->target = scsi_dev_desc[device].target; - pccb->lun = scsi_dev_desc[device].lun; - buf_addr = (unsigned long)buffer; - start = blknr; - blks = blkcnt; - debug("\nscsi_read: dev %d startblk " LBAF - ", blccnt " LBAF " buffer %lx\n", - device, start, blks, (unsigned long)buffer); - do { - pccb->pdata = (unsigned char *)buf_addr; -#ifdef CONFIG_SYS_64BIT_LBA - if (start > SCSI_LBA48_READ) { - unsigned long blocks; - blocks = min_t(lbaint_t, blks, SCSI_MAX_READ_BLK); - pccb->datalen = scsi_dev_desc[device].blksz * blocks; - scsi_setup_read16(pccb, start, blocks); - start += blocks; - blks -= blocks; - } else -#endif - if (blks > SCSI_MAX_READ_BLK) { - pccb->datalen = scsi_dev_desc[device].blksz * - SCSI_MAX_READ_BLK; - smallblks = SCSI_MAX_READ_BLK; - scsi_setup_read_ext(pccb, start, smallblks); - start += SCSI_MAX_READ_BLK; - blks -= SCSI_MAX_READ_BLK; - } - else { - pccb->datalen = scsi_dev_desc[device].blksz * blks; - smallblks = (unsigned short)blks; - scsi_setup_read_ext(pccb, start, smallblks); - start += blks; - blks=0; - } - debug("scsi_read_ext: startblk " LBAF - ", blccnt %x buffer %" PRIXPTR "\n", - start, smallblks, buf_addr); - if (scsi_exec(pccb) != true) { - scsi_print_error(pccb); - blkcnt -= blks; - break; - } - buf_addr+=pccb->datalen; - } while (blks != 0); - debug("scsi_read_ext: end startblk " LBAF - ", blccnt %x buffer %" PRIXPTR "\n", start, smallblks, buf_addr); - return blkcnt; -} - -/******************************************************************************* - * scsi_write - */ - -/* Almost the maximum amount of the scsi_ext command.. */ -#define SCSI_MAX_WRITE_BLK 0xFFFF - -static ulong scsi_write(struct blk_desc *block_dev, lbaint_t blknr, - lbaint_t blkcnt, const void *buffer) -{ - int device = block_dev->devnum; - lbaint_t start, blks; - uintptr_t buf_addr; - unsigned short smallblks; - ccb* pccb = (ccb *)&tempccb; - device &= 0xff; - /* Setup device - */ - pccb->target = scsi_dev_desc[device].target; - pccb->lun = scsi_dev_desc[device].lun; - buf_addr = (unsigned long)buffer; - start = blknr; - blks = blkcnt; - debug("\n%s: dev %d startblk " LBAF ", blccnt " LBAF " buffer %lx\n", - __func__, device, start, blks, (unsigned long)buffer); - do { - pccb->pdata = (unsigned char *)buf_addr; - if (blks > SCSI_MAX_WRITE_BLK) { - pccb->datalen = (scsi_dev_desc[device].blksz * - SCSI_MAX_WRITE_BLK); - smallblks = SCSI_MAX_WRITE_BLK; - scsi_setup_write_ext(pccb, start, smallblks); - start += SCSI_MAX_WRITE_BLK; - blks -= SCSI_MAX_WRITE_BLK; - } else { - pccb->datalen = scsi_dev_desc[device].blksz * blks; - smallblks = (unsigned short)blks; - scsi_setup_write_ext(pccb, start, smallblks); - start += blks; - blks = 0; - } - debug("%s: startblk " LBAF ", blccnt %x buffer %" PRIXPTR "\n", - __func__, start, smallblks, buf_addr); - if (scsi_exec(pccb) != true) { - scsi_print_error(pccb); - blkcnt -= blks; - break; - } - buf_addr += pccb->datalen; - } while (blks != 0); - debug("%s: end startblk " LBAF ", blccnt %x buffer %" PRIXPTR "\n", - __func__, start, smallblks, buf_addr); - return blkcnt; -} - -int scsi_get_disk_count(void) -{ - return scsi_max_devs; -} - -#if defined(CONFIG_PCI) && !defined(CONFIG_SCSI_AHCI_PLAT) -void scsi_init(void) -{ - int busdevfunc = -1; - int i; - /* - * Find a device from the list, this driver will support a single - * controller. - */ - for (i = 0; i < ARRAY_SIZE(scsi_device_list); i++) { - /* get PCI Device ID */ -#ifdef CONFIG_DM_PCI - struct udevice *dev; - int ret; - - ret = dm_pci_find_device(scsi_device_list[i].vendor, - scsi_device_list[i].device, 0, &dev); - if (!ret) { - busdevfunc = dm_pci_get_bdf(dev); - break; - } -#else - busdevfunc = pci_find_device(scsi_device_list[i].vendor, - scsi_device_list[i].device, - 0); -#endif - if (busdevfunc != -1) - break; - } - - if (busdevfunc == -1) { - printf("Error: SCSI Controller(s) "); - for (i = 0; i < ARRAY_SIZE(scsi_device_list); i++) { - printf("%04X:%04X ", - scsi_device_list[i].vendor, - scsi_device_list[i].device); - } - printf("not found\n"); - return; - } -#ifdef DEBUG - else { - printf("SCSI Controller (%04X,%04X) found (%d:%d:%d)\n", - scsi_device_list[i].vendor, - scsi_device_list[i].device, - (busdevfunc >> 16) & 0xFF, - (busdevfunc >> 11) & 0x1F, - (busdevfunc >> 8) & 0x7); - } -#endif - bootstage_start(BOOTSTAGE_ID_ACCUM_SCSI, "ahci"); - scsi_low_level_init(busdevfunc); - scsi_scan(1); - bootstage_accum(BOOTSTAGE_ID_ACCUM_SCSI); -} -#endif - -#ifdef CONFIG_PARTITIONS -struct blk_desc *scsi_get_dev(int dev) -{ - return (dev < CONFIG_SYS_SCSI_MAX_DEVICE) ? &scsi_dev_desc[dev] : NULL; -} -#endif - -#ifndef CONFIG_SPL_BUILD -/****************************************************************************** +/* * scsi boot command intepreter. Derived from diskboot */ -int do_scsiboot (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +int do_scsiboot(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) { return common_diskboot(cmdtp, "scsi", argc, argv); } -/********************************************************************************* +/* * scsi command intepreter */ -int do_scsi (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +int do_scsi(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) { switch (argc) { case 0: case 1: return CMD_RET_USAGE; - case 2: if (strncmp(argv[1], "res", 3) == 0) { printf("\nReset SCSI\n"); @@ -367,23 +39,15 @@ int do_scsi (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) return 0; } if (strncmp(argv[1], "inf", 3) == 0) { - int i; - for (i = 0; i < CONFIG_SYS_SCSI_MAX_DEVICE; ++i) { - if (scsi_dev_desc[i].type == DEV_TYPE_UNKNOWN) - continue; /* list only known devices */ - printf("SCSI dev. %d: ", i); - dev_print(&scsi_dev_desc[i]); - } + blk_list_devices(IF_TYPE_SCSI); return 0; } if (strncmp(argv[1], "dev", 3) == 0) { - if (scsi_curr_dev < 0 || - scsi_curr_dev >= CONFIG_SYS_SCSI_MAX_DEVICE) { + if (blk_print_device_num(IF_TYPE_SCSI, scsi_curr_dev)) { printf("\nno SCSI devices available\n"); - return 1; + return CMD_RET_FAILURE; } - printf("\n Device %d: ", scsi_curr_dev); - dev_print(&scsi_dev_desc[scsi_curr_dev]); + return 0; } if (strncmp(argv[1], "scan", 4) == 0) { @@ -391,46 +55,32 @@ int do_scsi (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) return 0; } if (strncmp(argv[1], "part", 4) == 0) { - int dev, ok; - for (ok = 0, dev = 0; - dev < CONFIG_SYS_SCSI_MAX_DEVICE; ++dev) { - if (scsi_dev_desc[dev].type != - DEV_TYPE_UNKNOWN) { - ok++; - if (dev) - printf("\n"); - debug("print_part of %x\n", dev); - part_print(&scsi_dev_desc[dev]); - } - } - if (!ok) + if (blk_list_part(IF_TYPE_SCSI)) printf("\nno SCSI devices available\n"); - return 1; + return 0; } return CMD_RET_USAGE; case 3: if (strncmp(argv[1], "dev", 3) == 0) { int dev = (int)simple_strtoul(argv[2], NULL, 10); - printf("\nSCSI device %d: ", dev); - if (dev >= CONFIG_SYS_SCSI_MAX_DEVICE) { - printf("unknown device\n"); - return 1; + + if (!blk_show_device(IF_TYPE_SCSI, dev)) { + scsi_curr_dev = dev; + printf("... is now current device\n"); + } else { + return CMD_RET_FAILURE; } - printf("\n Device %d: ", dev); - dev_print(&scsi_dev_desc[dev]); - if (scsi_dev_desc[dev].type == DEV_TYPE_UNKNOWN) - return 1; - scsi_curr_dev = dev; - printf("... is now current device\n"); return 0; } if (strncmp(argv[1], "part", 4) == 0) { int dev = (int)simple_strtoul(argv[2], NULL, 10); - if (scsi_dev_desc[dev].type != DEV_TYPE_UNKNOWN) - part_print(&scsi_dev_desc[dev]); - else - printf("\nSCSI device %d not available\n", dev); - return 1; + + if (blk_print_part_devnum(IF_TYPE_SCSI, dev)) { + printf("\nSCSI device %d not available\n", + dev); + return CMD_RET_FAILURE; + } + return 0; } return CMD_RET_USAGE; default: @@ -440,10 +90,11 @@ int do_scsi (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) ulong blk = simple_strtoul(argv[3], NULL, 16); ulong cnt = simple_strtoul(argv[4], NULL, 16); ulong n; + printf("\nSCSI read: device %d block # %ld, count %ld ... ", scsi_curr_dev, blk, cnt); - n = scsi_read(&scsi_dev_desc[scsi_curr_dev], - blk, cnt, (ulong *)addr); + n = blk_read_devnum(IF_TYPE_SCSI, scsi_curr_dev, blk, + cnt, (ulong *)addr); printf("%ld blocks read: %s\n", n, n == cnt ? "OK" : "ERROR"); return 0; @@ -452,10 +103,11 @@ int do_scsi (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) ulong blk = simple_strtoul(argv[3], NULL, 16); ulong cnt = simple_strtoul(argv[4], NULL, 16); ulong n; + printf("\nSCSI write: device %d block # %ld, count %ld ... ", scsi_curr_dev, blk, cnt); - n = scsi_write(&scsi_dev_desc[scsi_curr_dev], - blk, cnt, (ulong *)addr); + n = blk_write_devnum(IF_TYPE_SCSI, scsi_curr_dev, blk, + cnt, (ulong *)addr); printf("%ld blocks written: %s\n", n, n == cnt ? "OK" : "ERROR"); return 0; @@ -483,223 +135,3 @@ U_BOOT_CMD( "boot from SCSI device", "loadAddr dev:part" ); -#endif - -/* copy src to dest, skipping leading and trailing blanks - * and null terminate the string - */ -void scsi_ident_cpy(unsigned char *dest, unsigned char *src, unsigned int len) -{ - int start,end; - - start = 0; - while (start < len) { - if (src[start] != ' ') - break; - start++; - } - end = len-1; - while (end > start) { - if (src[end] != ' ') - break; - end--; - } - for (; start <= end; start++) - *dest ++= src[start]; - *dest='\0'; -} - - -/* Trim trailing blanks, and NUL-terminate string - */ -void scsi_trim_trail (unsigned char *str, unsigned int len) -{ - unsigned char *p = str + len - 1; - - while (len-- > 0) { - *p-- = '\0'; - if (*p != ' ') { - return; - } - } -} - -int scsi_read_capacity(ccb *pccb, lbaint_t *capacity, unsigned long *blksz) -{ - *capacity = 0; - - memset(pccb->cmd, '\0', sizeof(pccb->cmd)); - pccb->cmd[0] = SCSI_RD_CAPAC10; - pccb->cmd[1] = pccb->lun << 5; - pccb->cmdlen = 10; - pccb->msgout[0] = SCSI_IDENTIFY; /* NOT USED */ - - pccb->datalen = 8; - if (scsi_exec(pccb) != true) - return 1; - - *capacity = ((lbaint_t)pccb->pdata[0] << 24) | - ((lbaint_t)pccb->pdata[1] << 16) | - ((lbaint_t)pccb->pdata[2] << 8) | - ((lbaint_t)pccb->pdata[3]); - - if (*capacity != 0xffffffff) { - /* Read capacity (10) was sufficient for this drive. */ - *blksz = ((unsigned long)pccb->pdata[4] << 24) | - ((unsigned long)pccb->pdata[5] << 16) | - ((unsigned long)pccb->pdata[6] << 8) | - ((unsigned long)pccb->pdata[7]); - return 0; - } - - /* Read capacity (10) was insufficient. Use read capacity (16). */ - memset(pccb->cmd, '\0', sizeof(pccb->cmd)); - pccb->cmd[0] = SCSI_RD_CAPAC16; - pccb->cmd[1] = 0x10; - pccb->cmdlen = 16; - pccb->msgout[0] = SCSI_IDENTIFY; /* NOT USED */ - - pccb->datalen = 16; - if (scsi_exec(pccb) != true) - return 1; - - *capacity = ((uint64_t)pccb->pdata[0] << 56) | - ((uint64_t)pccb->pdata[1] << 48) | - ((uint64_t)pccb->pdata[2] << 40) | - ((uint64_t)pccb->pdata[3] << 32) | - ((uint64_t)pccb->pdata[4] << 24) | - ((uint64_t)pccb->pdata[5] << 16) | - ((uint64_t)pccb->pdata[6] << 8) | - ((uint64_t)pccb->pdata[7]); - - *blksz = ((uint64_t)pccb->pdata[8] << 56) | - ((uint64_t)pccb->pdata[9] << 48) | - ((uint64_t)pccb->pdata[10] << 40) | - ((uint64_t)pccb->pdata[11] << 32) | - ((uint64_t)pccb->pdata[12] << 24) | - ((uint64_t)pccb->pdata[13] << 16) | - ((uint64_t)pccb->pdata[14] << 8) | - ((uint64_t)pccb->pdata[15]); - - return 0; -} - - -/************************************************************************************ - * Some setup (fill-in) routines - */ -void scsi_setup_test_unit_ready(ccb * pccb) -{ - pccb->cmd[0] = SCSI_TST_U_RDY; - pccb->cmd[1] = pccb->lun << 5; - pccb->cmd[2] = 0; - pccb->cmd[3] = 0; - pccb->cmd[4] = 0; - pccb->cmd[5] = 0; - pccb->cmdlen = 6; - pccb->msgout[0] = SCSI_IDENTIFY; /* NOT USED */ -} - -/********************************************************************************* - * (re)-scan the scsi bus and reports scsi device info - * to the user if mode = 1 - */ -void scsi_scan(int mode) -{ - unsigned char i,perq,modi,lun; - lbaint_t capacity; - unsigned long blksz; - ccb* pccb=(ccb *)&tempccb; - - if (mode == 1) - printf("scanning bus for devices...\n"); - for (i = 0; i < CONFIG_SYS_SCSI_MAX_DEVICE; i++) { - scsi_dev_desc[i].target = 0xff; - scsi_dev_desc[i].lun = 0xff; - scsi_dev_desc[i].lba = 0; - scsi_dev_desc[i].blksz = 0; - scsi_dev_desc[i].log2blksz = - LOG2_INVALID(typeof(scsi_dev_desc[i].log2blksz)); - scsi_dev_desc[i].type = DEV_TYPE_UNKNOWN; - scsi_dev_desc[i].vendor[0] = 0; - scsi_dev_desc[i].product[0] = 0; - scsi_dev_desc[i].revision[0] = 0; - scsi_dev_desc[i].removable = false; - scsi_dev_desc[i].if_type = IF_TYPE_SCSI; - scsi_dev_desc[i].devnum = i; - scsi_dev_desc[i].part_type = PART_TYPE_UNKNOWN; - scsi_dev_desc[i].block_read = scsi_read; - scsi_dev_desc[i].block_write = scsi_write; - } - scsi_max_devs = 0; - for (i = 0; i < CONFIG_SYS_SCSI_MAX_SCSI_ID; i++) { - pccb->target = i; - for (lun = 0; lun < CONFIG_SYS_SCSI_MAX_LUN; lun++) { - pccb->lun = lun; - pccb->pdata = (unsigned char *)&tempbuff; - pccb->datalen = 512; - scsi_setup_inquiry(pccb); - if (scsi_exec(pccb) != true) { - if(pccb->contr_stat==SCSI_SEL_TIME_OUT) { - debug("Selection timeout ID %d\n", - pccb->target); - continue; /* selection timeout => assuming no device present */ - } - scsi_print_error(pccb); - continue; - } - perq = tempbuff[0]; - modi = tempbuff[1]; - if ((perq & 0x1f) == 0x1f) - continue; /* skip unknown devices */ - if ((modi & 0x80) == 0x80) /* drive is removable */ - scsi_dev_desc[scsi_max_devs].removable = true; - /* get info for this device */ - scsi_ident_cpy((unsigned char *)&scsi_dev_desc[scsi_max_devs].vendor[0], - &tempbuff[8], 8); - scsi_ident_cpy((unsigned char *)&scsi_dev_desc[scsi_max_devs].product[0], - &tempbuff[16], 16); - scsi_ident_cpy((unsigned char *)&scsi_dev_desc[scsi_max_devs].revision[0], - &tempbuff[32], 4); - scsi_dev_desc[scsi_max_devs].target = pccb->target; - scsi_dev_desc[scsi_max_devs].lun = pccb->lun; - - pccb->datalen = 0; - scsi_setup_test_unit_ready(pccb); - if (scsi_exec(pccb) != true) { - if (scsi_dev_desc[scsi_max_devs].removable) { - scsi_dev_desc[scsi_max_devs].type = - perq; - goto removable; - } - scsi_print_error(pccb); - continue; - } - if (scsi_read_capacity(pccb, &capacity, &blksz)) { - scsi_print_error(pccb); - continue; - } - scsi_dev_desc[scsi_max_devs].lba = capacity; - scsi_dev_desc[scsi_max_devs].blksz = blksz; - scsi_dev_desc[scsi_max_devs].log2blksz = - LOG2(scsi_dev_desc[scsi_max_devs].blksz); - scsi_dev_desc[scsi_max_devs].type = perq; - part_init(&scsi_dev_desc[scsi_max_devs]); -removable: - if(mode==1) { - printf (" Device %d: ", scsi_max_devs); - dev_print(&scsi_dev_desc[scsi_max_devs]); - } /* if mode */ - scsi_max_devs++; - } /* next LUN */ - } - if (scsi_max_devs > 0) - scsi_curr_dev = 0; - else - scsi_curr_dev = -1; - - printf("Found %d device(s).\n", scsi_max_devs); -#ifndef CONFIG_SPL_BUILD - setenv_ulong("scsidevs", scsi_max_devs); -#endif -} diff --git a/common/Makefile b/common/Makefile index b23f312006..397df61016 100644 --- a/common/Makefile +++ b/common/Makefile @@ -84,6 +84,7 @@ obj-$(CONFIG_LCD_ROTATION) += lcd_console_rotation.o obj-$(CONFIG_LCD_DT_SIMPLEFB) += lcd_simplefb.o obj-$(CONFIG_LYNXKDI) += lynxkdi.o obj-$(CONFIG_MENU) += menu.o +obj-$(CONFIG_SCSI) += scsi.o obj-$(CONFIG_UPDATE_TFTP) += update.o obj-$(CONFIG_DFU_TFTP) += update.o obj-$(CONFIG_USB_KEYBOARD) += usb_kbd.o @@ -112,6 +113,9 @@ obj-$(CONFIG_ENV_IS_IN_NAND) += env_nand.o obj-$(CONFIG_ENV_IS_IN_SPI_FLASH) += env_sf.o obj-$(CONFIG_ENV_IS_IN_FLASH) += env_flash.o endif +ifdef CONFIG_SPL_SATA_SUPPORT +obj-$(CONFIG_SCSI) += scsi.o +endif endif #environment obj-y += env_common.o diff --git a/common/scsi.c b/common/scsi.c new file mode 100644 index 0000000000..a336a10753 --- /dev/null +++ b/common/scsi.c @@ -0,0 +1,567 @@ +/* + * (C) Copyright 2001 + * Denis Peter, MPL AG Switzerland + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include + +#ifdef CONFIG_SCSI_DEV_LIST +#define SCSI_DEV_LIST CONFIG_SCSI_DEV_LIST +#else +#ifdef CONFIG_SCSI_SYM53C8XX +#define SCSI_VEND_ID 0x1000 +#ifndef CONFIG_SCSI_DEV_ID +#define SCSI_DEV_ID 0x0001 +#else +#define SCSI_DEV_ID CONFIG_SCSI_DEV_ID +#endif +#elif defined CONFIG_SATA_ULI5288 + +#define SCSI_VEND_ID 0x10b9 +#define SCSI_DEV_ID 0x5288 + +#elif !defined(CONFIG_SCSI_AHCI_PLAT) +#error no scsi device defined +#endif +#define SCSI_DEV_LIST {SCSI_VEND_ID, SCSI_DEV_ID} +#endif + +#if defined(CONFIG_PCI) && !defined(CONFIG_SCSI_AHCI_PLAT) +const struct pci_device_id scsi_device_list[] = { SCSI_DEV_LIST }; +#endif +static ccb tempccb; /* temporary scsi command buffer */ + +static unsigned char tempbuff[512]; /* temporary data buffer */ + +static int scsi_max_devs; /* number of highest available scsi device */ + +static int scsi_curr_dev; /* current device */ + +static struct blk_desc scsi_dev_desc[CONFIG_SYS_SCSI_MAX_DEVICE]; + +/* almost the maximum amount of the scsi_ext command.. */ +#define SCSI_MAX_READ_BLK 0xFFFF +#define SCSI_LBA48_READ 0xFFFFFFF + +#ifdef CONFIG_SYS_64BIT_LBA +void scsi_setup_read16(ccb *pccb, lbaint_t start, unsigned long blocks) +{ + pccb->cmd[0] = SCSI_READ16; + pccb->cmd[1] = pccb->lun << 5; + pccb->cmd[2] = (unsigned char)(start >> 56) & 0xff; + pccb->cmd[3] = (unsigned char)(start >> 48) & 0xff; + pccb->cmd[4] = (unsigned char)(start >> 40) & 0xff; + pccb->cmd[5] = (unsigned char)(start >> 32) & 0xff; + pccb->cmd[6] = (unsigned char)(start >> 24) & 0xff; + pccb->cmd[7] = (unsigned char)(start >> 16) & 0xff; + pccb->cmd[8] = (unsigned char)(start >> 8) & 0xff; + pccb->cmd[9] = (unsigned char)start & 0xff; + pccb->cmd[10] = 0; + pccb->cmd[11] = (unsigned char)(blocks >> 24) & 0xff; + pccb->cmd[12] = (unsigned char)(blocks >> 16) & 0xff; + pccb->cmd[13] = (unsigned char)(blocks >> 8) & 0xff; + pccb->cmd[14] = (unsigned char)blocks & 0xff; + pccb->cmd[15] = 0; + pccb->cmdlen = 16; + pccb->msgout[0] = SCSI_IDENTIFY; /* NOT USED */ + debug("scsi_setup_read16: cmd: %02X %02X startblk %02X%02X%02X%02X%02X%02X%02X%02X blccnt %02X%02X%02X%02X\n", + pccb->cmd[0], pccb->cmd[1], + pccb->cmd[2], pccb->cmd[3], pccb->cmd[4], pccb->cmd[5], + pccb->cmd[6], pccb->cmd[7], pccb->cmd[8], pccb->cmd[9], + pccb->cmd[11], pccb->cmd[12], pccb->cmd[13], pccb->cmd[14]); +} +#endif + +void scsi_setup_read_ext(ccb *pccb, lbaint_t start, unsigned short blocks) +{ + pccb->cmd[0] = SCSI_READ10; + pccb->cmd[1] = pccb->lun << 5; + pccb->cmd[2] = (unsigned char)(start >> 24) & 0xff; + pccb->cmd[3] = (unsigned char)(start >> 16) & 0xff; + pccb->cmd[4] = (unsigned char)(start >> 8) & 0xff; + pccb->cmd[5] = (unsigned char)start & 0xff; + pccb->cmd[6] = 0; + pccb->cmd[7] = (unsigned char)(blocks >> 8) & 0xff; + pccb->cmd[8] = (unsigned char)blocks & 0xff; + pccb->cmd[6] = 0; + pccb->cmdlen = 10; + pccb->msgout[0] = SCSI_IDENTIFY; /* NOT USED */ + debug("scsi_setup_read_ext: cmd: %02X %02X startblk %02X%02X%02X%02X blccnt %02X%02X\n", + pccb->cmd[0], pccb->cmd[1], + pccb->cmd[2], pccb->cmd[3], pccb->cmd[4], pccb->cmd[5], + pccb->cmd[7], pccb->cmd[8]); +} + +void scsi_setup_write_ext(ccb *pccb, lbaint_t start, unsigned short blocks) +{ + pccb->cmd[0] = SCSI_WRITE10; + pccb->cmd[1] = pccb->lun << 5; + pccb->cmd[2] = (unsigned char)(start >> 24) & 0xff; + pccb->cmd[3] = (unsigned char)(start >> 16) & 0xff; + pccb->cmd[4] = (unsigned char)(start >> 8) & 0xff; + pccb->cmd[5] = (unsigned char)start & 0xff; + pccb->cmd[6] = 0; + pccb->cmd[7] = ((unsigned char)(blocks >> 8)) & 0xff; + pccb->cmd[8] = (unsigned char)blocks & 0xff; + pccb->cmd[9] = 0; + pccb->cmdlen = 10; + pccb->msgout[0] = SCSI_IDENTIFY; /* NOT USED */ + debug("%s: cmd: %02X %02X startblk %02X%02X%02X%02X blccnt %02X%02X\n", + __func__, + pccb->cmd[0], pccb->cmd[1], + pccb->cmd[2], pccb->cmd[3], pccb->cmd[4], pccb->cmd[5], + pccb->cmd[7], pccb->cmd[8]); +} + +void scsi_setup_read6(ccb *pccb, lbaint_t start, unsigned short blocks) +{ + pccb->cmd[0] = SCSI_READ6; + pccb->cmd[1] = pccb->lun << 5 | ((unsigned char)(start >> 16) & 0x1f); + pccb->cmd[2] = (unsigned char)(start >> 8) & 0xff; + pccb->cmd[3] = (unsigned char)start & 0xff; + pccb->cmd[4] = (unsigned char)blocks & 0xff; + pccb->cmd[5] = 0; + pccb->cmdlen = 6; + pccb->msgout[0] = SCSI_IDENTIFY; /* NOT USED */ + debug("scsi_setup_read6: cmd: %02X %02X startblk %02X%02X blccnt %02X\n", + pccb->cmd[0], pccb->cmd[1], + pccb->cmd[2], pccb->cmd[3], pccb->cmd[4]); +} + + +void scsi_setup_inquiry(ccb *pccb) +{ + pccb->cmd[0] = SCSI_INQUIRY; + pccb->cmd[1] = pccb->lun << 5; + pccb->cmd[2] = 0; + pccb->cmd[3] = 0; + if (pccb->datalen > 255) + pccb->cmd[4] = 255; + else + pccb->cmd[4] = (unsigned char)pccb->datalen; + pccb->cmd[5] = 0; + pccb->cmdlen = 6; + pccb->msgout[0] = SCSI_IDENTIFY; /* NOT USED */ +} + +static ulong scsi_read(struct blk_desc *block_dev, lbaint_t blknr, + lbaint_t blkcnt, void *buffer) +{ + int device = block_dev->devnum; + lbaint_t start, blks; + uintptr_t buf_addr; + unsigned short smallblks = 0; + ccb *pccb = (ccb *)&tempccb; + device &= 0xff; + + /* Setup device */ + pccb->target = scsi_dev_desc[device].target; + pccb->lun = scsi_dev_desc[device].lun; + buf_addr = (unsigned long)buffer; + start = blknr; + blks = blkcnt; + debug("\nscsi_read: dev %d startblk " LBAF + ", blccnt " LBAF " buffer %lx\n", + device, start, blks, (unsigned long)buffer); + do { + pccb->pdata = (unsigned char *)buf_addr; +#ifdef CONFIG_SYS_64BIT_LBA + if (start > SCSI_LBA48_READ) { + unsigned long blocks; + blocks = min_t(lbaint_t, blks, SCSI_MAX_READ_BLK); + pccb->datalen = scsi_dev_desc[device].blksz * blocks; + scsi_setup_read16(pccb, start, blocks); + start += blocks; + blks -= blocks; + } else +#endif + if (blks > SCSI_MAX_READ_BLK) { + pccb->datalen = scsi_dev_desc[device].blksz * + SCSI_MAX_READ_BLK; + smallblks = SCSI_MAX_READ_BLK; + scsi_setup_read_ext(pccb, start, smallblks); + start += SCSI_MAX_READ_BLK; + blks -= SCSI_MAX_READ_BLK; + } else { + pccb->datalen = scsi_dev_desc[device].blksz * blks; + smallblks = (unsigned short)blks; + scsi_setup_read_ext(pccb, start, smallblks); + start += blks; + blks = 0; + } + debug("scsi_read_ext: startblk " LBAF + ", blccnt %x buffer %" PRIXPTR "\n", + start, smallblks, buf_addr); + if (scsi_exec(pccb) != true) { + scsi_print_error(pccb); + blkcnt -= blks; + break; + } + buf_addr += pccb->datalen; + } while (blks != 0); + debug("scsi_read_ext: end startblk " LBAF + ", blccnt %x buffer %" PRIXPTR "\n", start, smallblks, buf_addr); + return blkcnt; +} + +/******************************************************************************* + * scsi_write + */ + +/* Almost the maximum amount of the scsi_ext command.. */ +#define SCSI_MAX_WRITE_BLK 0xFFFF + +static ulong scsi_write(struct blk_desc *block_dev, lbaint_t blknr, + lbaint_t blkcnt, const void *buffer) +{ + int device = block_dev->devnum; + lbaint_t start, blks; + uintptr_t buf_addr; + unsigned short smallblks; + ccb *pccb = (ccb *)&tempccb; + + device &= 0xff; + + /* Setup device */ + pccb->target = scsi_dev_desc[device].target; + pccb->lun = scsi_dev_desc[device].lun; + buf_addr = (unsigned long)buffer; + start = blknr; + blks = blkcnt; + debug("\n%s: dev %d startblk " LBAF ", blccnt " LBAF " buffer %lx\n", + __func__, device, start, blks, (unsigned long)buffer); + do { + pccb->pdata = (unsigned char *)buf_addr; + if (blks > SCSI_MAX_WRITE_BLK) { + pccb->datalen = (scsi_dev_desc[device].blksz * + SCSI_MAX_WRITE_BLK); + smallblks = SCSI_MAX_WRITE_BLK; + scsi_setup_write_ext(pccb, start, smallblks); + start += SCSI_MAX_WRITE_BLK; + blks -= SCSI_MAX_WRITE_BLK; + } else { + pccb->datalen = scsi_dev_desc[device].blksz * blks; + smallblks = (unsigned short)blks; + scsi_setup_write_ext(pccb, start, smallblks); + start += blks; + blks = 0; + } + debug("%s: startblk " LBAF ", blccnt %x buffer %" PRIXPTR "\n", + __func__, start, smallblks, buf_addr); + if (scsi_exec(pccb) != true) { + scsi_print_error(pccb); + blkcnt -= blks; + break; + } + buf_addr += pccb->datalen; + } while (blks != 0); + debug("%s: end startblk " LBAF ", blccnt %x buffer %" PRIXPTR "\n", + __func__, start, smallblks, buf_addr); + return blkcnt; +} + +int scsi_get_disk_count(void) +{ + return scsi_max_devs; +} + +#if defined(CONFIG_PCI) && !defined(CONFIG_SCSI_AHCI_PLAT) +void scsi_init(void) +{ + int busdevfunc = -1; + int i; + /* + * Find a device from the list, this driver will support a single + * controller. + */ + for (i = 0; i < ARRAY_SIZE(scsi_device_list); i++) { + /* get PCI Device ID */ +#ifdef CONFIG_DM_PCI + struct udevice *dev; + int ret; + + ret = dm_pci_find_device(scsi_device_list[i].vendor, + scsi_device_list[i].device, 0, &dev); + if (!ret) { + busdevfunc = dm_pci_get_bdf(dev); + break; + } +#else + busdevfunc = pci_find_device(scsi_device_list[i].vendor, + scsi_device_list[i].device, + 0); +#endif + if (busdevfunc != -1) + break; + } + + if (busdevfunc == -1) { + printf("Error: SCSI Controller(s) "); + for (i = 0; i < ARRAY_SIZE(scsi_device_list); i++) { + printf("%04X:%04X ", + scsi_device_list[i].vendor, + scsi_device_list[i].device); + } + printf("not found\n"); + return; + } +#ifdef DEBUG + else { + printf("SCSI Controller (%04X,%04X) found (%d:%d:%d)\n", + scsi_device_list[i].vendor, + scsi_device_list[i].device, + (busdevfunc >> 16) & 0xFF, + (busdevfunc >> 11) & 0x1F, + (busdevfunc >> 8) & 0x7); + } +#endif + bootstage_start(BOOTSTAGE_ID_ACCUM_SCSI, "ahci"); + scsi_low_level_init(busdevfunc); + scsi_scan(1); + bootstage_accum(BOOTSTAGE_ID_ACCUM_SCSI); +} +#endif + +#ifdef CONFIG_PARTITIONS +struct blk_desc *scsi_get_dev(int dev) +{ + return (dev < CONFIG_SYS_SCSI_MAX_DEVICE) ? &scsi_dev_desc[dev] : NULL; +} +#endif + +/* copy src to dest, skipping leading and trailing blanks + * and null terminate the string + */ +void scsi_ident_cpy(unsigned char *dest, unsigned char *src, unsigned int len) +{ + int start, end; + + start = 0; + while (start < len) { + if (src[start] != ' ') + break; + start++; + } + end = len-1; + while (end > start) { + if (src[end] != ' ') + break; + end--; + } + for (; start <= end; start++) + *dest ++= src[start]; + *dest = '\0'; +} + + +/* Trim trailing blanks, and NUL-terminate string + */ +void scsi_trim_trail(unsigned char *str, unsigned int len) +{ + unsigned char *p = str + len - 1; + + while (len-- > 0) { + *p-- = '\0'; + if (*p != ' ') + return; + } +} + +int scsi_read_capacity(ccb *pccb, lbaint_t *capacity, unsigned long *blksz) +{ + *capacity = 0; + + memset(pccb->cmd, '\0', sizeof(pccb->cmd)); + pccb->cmd[0] = SCSI_RD_CAPAC10; + pccb->cmd[1] = pccb->lun << 5; + pccb->cmdlen = 10; + pccb->msgout[0] = SCSI_IDENTIFY; /* NOT USED */ + + pccb->datalen = 8; + if (scsi_exec(pccb) != true) + return 1; + + *capacity = ((lbaint_t)pccb->pdata[0] << 24) | + ((lbaint_t)pccb->pdata[1] << 16) | + ((lbaint_t)pccb->pdata[2] << 8) | + ((lbaint_t)pccb->pdata[3]); + + if (*capacity != 0xffffffff) { + /* Read capacity (10) was sufficient for this drive. */ + *blksz = ((unsigned long)pccb->pdata[4] << 24) | + ((unsigned long)pccb->pdata[5] << 16) | + ((unsigned long)pccb->pdata[6] << 8) | + ((unsigned long)pccb->pdata[7]); + return 0; + } + + /* Read capacity (10) was insufficient. Use read capacity (16). */ + memset(pccb->cmd, '\0', sizeof(pccb->cmd)); + pccb->cmd[0] = SCSI_RD_CAPAC16; + pccb->cmd[1] = 0x10; + pccb->cmdlen = 16; + pccb->msgout[0] = SCSI_IDENTIFY; /* NOT USED */ + + pccb->datalen = 16; + if (scsi_exec(pccb) != true) + return 1; + + *capacity = ((uint64_t)pccb->pdata[0] << 56) | + ((uint64_t)pccb->pdata[1] << 48) | + ((uint64_t)pccb->pdata[2] << 40) | + ((uint64_t)pccb->pdata[3] << 32) | + ((uint64_t)pccb->pdata[4] << 24) | + ((uint64_t)pccb->pdata[5] << 16) | + ((uint64_t)pccb->pdata[6] << 8) | + ((uint64_t)pccb->pdata[7]); + + *blksz = ((uint64_t)pccb->pdata[8] << 56) | + ((uint64_t)pccb->pdata[9] << 48) | + ((uint64_t)pccb->pdata[10] << 40) | + ((uint64_t)pccb->pdata[11] << 32) | + ((uint64_t)pccb->pdata[12] << 24) | + ((uint64_t)pccb->pdata[13] << 16) | + ((uint64_t)pccb->pdata[14] << 8) | + ((uint64_t)pccb->pdata[15]); + + return 0; +} + + +/* + * Some setup (fill-in) routines + */ +void scsi_setup_test_unit_ready(ccb *pccb) +{ + pccb->cmd[0] = SCSI_TST_U_RDY; + pccb->cmd[1] = pccb->lun << 5; + pccb->cmd[2] = 0; + pccb->cmd[3] = 0; + pccb->cmd[4] = 0; + pccb->cmd[5] = 0; + pccb->cmdlen = 6; + pccb->msgout[0] = SCSI_IDENTIFY; /* NOT USED */ +} + +/* + * (re)-scan the scsi bus and reports scsi device info + * to the user if mode = 1 + */ +void scsi_scan(int mode) +{ + unsigned char i, perq, modi, lun; + lbaint_t capacity; + unsigned long blksz; + ccb *pccb = (ccb *)&tempccb; + + if (mode == 1) + printf("scanning bus for devices...\n"); + for (i = 0; i < CONFIG_SYS_SCSI_MAX_DEVICE; i++) { + scsi_dev_desc[i].target = 0xff; + scsi_dev_desc[i].lun = 0xff; + scsi_dev_desc[i].lba = 0; + scsi_dev_desc[i].blksz = 0; + scsi_dev_desc[i].log2blksz = + LOG2_INVALID(typeof(scsi_dev_desc[i].log2blksz)); + scsi_dev_desc[i].type = DEV_TYPE_UNKNOWN; + scsi_dev_desc[i].vendor[0] = 0; + scsi_dev_desc[i].product[0] = 0; + scsi_dev_desc[i].revision[0] = 0; + scsi_dev_desc[i].removable = false; + scsi_dev_desc[i].if_type = IF_TYPE_SCSI; + scsi_dev_desc[i].devnum = i; + scsi_dev_desc[i].part_type = PART_TYPE_UNKNOWN; + scsi_dev_desc[i].block_read = scsi_read; + scsi_dev_desc[i].block_write = scsi_write; + } + scsi_max_devs = 0; + for (i = 0; i < CONFIG_SYS_SCSI_MAX_SCSI_ID; i++) { + pccb->target = i; + for (lun = 0; lun < CONFIG_SYS_SCSI_MAX_LUN; lun++) { + pccb->lun = lun; + pccb->pdata = (unsigned char *)&tempbuff; + pccb->datalen = 512; + scsi_setup_inquiry(pccb); + if (scsi_exec(pccb) != true) { + if (pccb->contr_stat == SCSI_SEL_TIME_OUT) { + /* + * selection timeout => assuming no + * device present + */ + debug("Selection timeout ID %d\n", + pccb->target); + continue; + } + scsi_print_error(pccb); + continue; + } + perq = tempbuff[0]; + modi = tempbuff[1]; + if ((perq & 0x1f) == 0x1f) + continue; /* skip unknown devices */ + if ((modi & 0x80) == 0x80) /* drive is removable */ + scsi_dev_desc[scsi_max_devs].removable = true; + /* get info for this device */ + scsi_ident_cpy((unsigned char *)&scsi_dev_desc + [scsi_max_devs].vendor[0], + &tempbuff[8], 8); + scsi_ident_cpy((unsigned char *)&scsi_dev_desc + [scsi_max_devs].product[0], + &tempbuff[16], 16); + scsi_ident_cpy((unsigned char *)&scsi_dev_desc + [scsi_max_devs].revision[0], + &tempbuff[32], 4); + scsi_dev_desc[scsi_max_devs].target = pccb->target; + scsi_dev_desc[scsi_max_devs].lun = pccb->lun; + + pccb->datalen = 0; + scsi_setup_test_unit_ready(pccb); + if (scsi_exec(pccb) != true) { + if (scsi_dev_desc[scsi_max_devs].removable) { + scsi_dev_desc[scsi_max_devs].type = + perq; + goto removable; + } + scsi_print_error(pccb); + continue; + } + if (scsi_read_capacity(pccb, &capacity, &blksz)) { + scsi_print_error(pccb); + continue; + } + scsi_dev_desc[scsi_max_devs].lba = capacity; + scsi_dev_desc[scsi_max_devs].blksz = blksz; + scsi_dev_desc[scsi_max_devs].log2blksz = + LOG2(scsi_dev_desc[scsi_max_devs].blksz); + scsi_dev_desc[scsi_max_devs].type = perq; + part_init(&scsi_dev_desc[scsi_max_devs]); +removable: + if (mode == 1) { + printf(" Device %d: ", scsi_max_devs); + dev_print(&scsi_dev_desc[scsi_max_devs]); + } /* if mode */ + scsi_max_devs++; + } /* next LUN */ + } + if (scsi_max_devs > 0) + scsi_curr_dev = 0; + else + scsi_curr_dev = -1; + + printf("Found %d device(s).\n", scsi_max_devs); +#ifndef CONFIG_SPL_BUILD + setenv_ulong("scsidevs", scsi_max_devs); +#endif +} + +U_BOOT_LEGACY_BLK(scsi) = { + .if_typename = "sata", + .if_type = IF_TYPE_SCSI, + .max_devs = CONFIG_SYS_SCSI_MAX_DEVICE, + .desc = scsi_dev_desc, +}; From e9be1ee75ed27c4281cad5168b6c51d26b2e8a15 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 1 May 2016 11:36:10 -0600 Subject: [PATCH 058/162] dm: ide: Separate the non-command code into its own file At present the IDE command code includes both the command-processing code and the core IDE functions and data structures. Separate the latter into its own file, adding functions as needed to avoid the command code accessing data structures directly. With this commit: - Most CONFIG option are referenced from the non-command code - The concept of a 'current IDE device' is confined to the command code This will make it easier to convert this code to driver model. Signed-off-by: Simon Glass --- cmd/ide.c | 1297 +---------------------------------------------- common/Makefile | 1 + common/ide.c | 1206 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 1228 insertions(+), 1276 deletions(-) create mode 100644 common/ide.c diff --git a/cmd/ide.c b/cmd/ide.c index db26f4320d..c942744e72 100644 --- a/cmd/ide.c +++ b/cmd/ide.c @@ -29,717 +29,9 @@ # include #endif -#ifdef __PPC__ -# define EIEIO __asm__ volatile ("eieio") -# define SYNC __asm__ volatile ("sync") -#else -# define EIEIO /* nothing */ -# define SYNC /* nothing */ -#endif - -/* ------------------------------------------------------------------------- */ - /* Current I/O Device */ static int curr_device = -1; -/* Current offset for IDE0 / IDE1 bus access */ -ulong ide_bus_offset[CONFIG_SYS_IDE_MAXBUS] = { -#if defined(CONFIG_SYS_ATA_IDE0_OFFSET) - CONFIG_SYS_ATA_IDE0_OFFSET, -#endif -#if defined(CONFIG_SYS_ATA_IDE1_OFFSET) && (CONFIG_SYS_IDE_MAXBUS > 1) - CONFIG_SYS_ATA_IDE1_OFFSET, -#endif -}; - -static int ide_bus_ok[CONFIG_SYS_IDE_MAXBUS]; - -struct blk_desc ide_dev_desc[CONFIG_SYS_IDE_MAXDEVICE]; -/* ------------------------------------------------------------------------- */ - -#define IDE_TIME_OUT 2000 /* 2 sec timeout */ - -#define ATAPI_TIME_OUT 7000 /* 7 sec timeout (5 sec seems to work...) */ - -#define IDE_SPIN_UP_TIME_OUT 5000 /* 5 sec spin-up timeout */ - -#ifndef CONFIG_SYS_ATA_PORT_ADDR -#define CONFIG_SYS_ATA_PORT_ADDR(port) (port) -#endif - -#ifndef CONFIG_IDE_LED /* define LED macros, they are not used anyways */ -# define DEVICE_LED(x) 0 -# define LED_IDE1 1 -# define LED_IDE2 2 -#endif - -#ifdef CONFIG_IDE_RESET -extern void ide_set_reset(int idereset); - -static void ide_reset(void) -{ - int i; - - curr_device = -1; - for (i = 0; i < CONFIG_SYS_IDE_MAXBUS; ++i) - ide_bus_ok[i] = 0; - for (i = 0; i < CONFIG_SYS_IDE_MAXDEVICE; ++i) - ide_dev_desc[i].type = DEV_TYPE_UNKNOWN; - - ide_set_reset(1); /* assert reset */ - - /* the reset signal shall be asserted for et least 25 us */ - udelay(25); - - WATCHDOG_RESET(); - - /* de-assert RESET signal */ - ide_set_reset(0); - - /* wait 250 ms */ - for (i = 0; i < 250; ++i) - udelay(1000); -} -#else -#define ide_reset() /* dummy */ -#endif /* CONFIG_IDE_RESET */ - -/* - * Wait until Busy bit is off, or timeout (in ms) - * Return last status - */ -static uchar ide_wait(int dev, ulong t) -{ - ulong delay = 10 * t; /* poll every 100 us */ - uchar c; - - while ((c = ide_inb(dev, ATA_STATUS)) & ATA_STAT_BUSY) { - udelay(100); - if (delay-- == 0) - break; - } - return c; -} - -/* - * copy src to dest, skipping leading and trailing blanks and null - * terminate the string - * "len" is the size of available memory including the terminating '\0' - */ -static void ident_cpy(unsigned char *dst, unsigned char *src, - unsigned int len) -{ - unsigned char *end, *last; - - last = dst; - end = src + len - 1; - - /* reserve space for '\0' */ - if (len < 2) - goto OUT; - - /* skip leading white space */ - while ((*src) && (src < end) && (*src == ' ')) - ++src; - - /* copy string, omitting trailing white space */ - while ((*src) && (src < end)) { - *dst++ = *src; - if (*src++ != ' ') - last = dst; - } -OUT: - *last = '\0'; -} - -#ifdef CONFIG_ATAPI -/**************************************************************************** - * ATAPI Support - */ - -#if defined(CONFIG_IDE_SWAP_IO) -/* since ATAPI may use commands with not 4 bytes alligned length - * we have our own transfer functions, 2 bytes alligned */ -__weak void ide_output_data_shorts(int dev, ushort *sect_buf, int shorts) -{ - ushort *dbuf; - volatile ushort *pbuf; - - pbuf = (ushort *)(ATA_CURR_BASE(dev) + ATA_DATA_REG); - dbuf = (ushort *)sect_buf; - - debug("in output data shorts base for read is %lx\n", - (unsigned long) pbuf); - - while (shorts--) { - EIEIO; - *pbuf = *dbuf++; - } -} - -__weak void ide_input_data_shorts(int dev, ushort *sect_buf, int shorts) -{ - ushort *dbuf; - volatile ushort *pbuf; - - pbuf = (ushort *)(ATA_CURR_BASE(dev) + ATA_DATA_REG); - dbuf = (ushort *)sect_buf; - - debug("in input data shorts base for read is %lx\n", - (unsigned long) pbuf); - - while (shorts--) { - EIEIO; - *dbuf++ = *pbuf; - } -} - -#else /* ! CONFIG_IDE_SWAP_IO */ -__weak void ide_output_data_shorts(int dev, ushort *sect_buf, int shorts) -{ - outsw(ATA_CURR_BASE(dev) + ATA_DATA_REG, sect_buf, shorts); -} - -__weak void ide_input_data_shorts(int dev, ushort *sect_buf, int shorts) -{ - insw(ATA_CURR_BASE(dev) + ATA_DATA_REG, sect_buf, shorts); -} - -#endif /* CONFIG_IDE_SWAP_IO */ - -/* - * Wait until (Status & mask) == res, or timeout (in ms) - * Return last status - * This is used since some ATAPI CD ROMs clears their Busy Bit first - * and then they set their DRQ Bit - */ -static uchar atapi_wait_mask(int dev, ulong t, uchar mask, uchar res) -{ - ulong delay = 10 * t; /* poll every 100 us */ - uchar c; - - /* prevents to read the status before valid */ - c = ide_inb(dev, ATA_DEV_CTL); - - while (((c = ide_inb(dev, ATA_STATUS)) & mask) != res) { - /* break if error occurs (doesn't make sense to wait more) */ - if ((c & ATA_STAT_ERR) == ATA_STAT_ERR) - break; - udelay(100); - if (delay-- == 0) - break; - } - return c; -} - -/* - * issue an atapi command - */ -unsigned char atapi_issue(int device, unsigned char *ccb, int ccblen, - unsigned char *buffer, int buflen) -{ - unsigned char c, err, mask, res; - int n; - - ide_led(DEVICE_LED(device), 1); /* LED on */ - - /* Select device - */ - mask = ATA_STAT_BUSY | ATA_STAT_DRQ; - res = 0; - ide_outb(device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device)); - c = atapi_wait_mask(device, ATAPI_TIME_OUT, mask, res); - if ((c & mask) != res) { - printf("ATAPI_ISSUE: device %d not ready status %X\n", device, - c); - err = 0xFF; - goto AI_OUT; - } - /* write taskfile */ - ide_outb(device, ATA_ERROR_REG, 0); /* no DMA, no overlaped */ - ide_outb(device, ATA_SECT_CNT, 0); - ide_outb(device, ATA_SECT_NUM, 0); - ide_outb(device, ATA_CYL_LOW, (unsigned char) (buflen & 0xFF)); - ide_outb(device, ATA_CYL_HIGH, - (unsigned char) ((buflen >> 8) & 0xFF)); - ide_outb(device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device)); - - ide_outb(device, ATA_COMMAND, ATAPI_CMD_PACKET); - udelay(50); - - mask = ATA_STAT_DRQ | ATA_STAT_BUSY | ATA_STAT_ERR; - res = ATA_STAT_DRQ; - c = atapi_wait_mask(device, ATAPI_TIME_OUT, mask, res); - - if ((c & mask) != res) { /* DRQ must be 1, BSY 0 */ - printf("ATAPI_ISSUE: Error (no IRQ) before sending ccb dev %d status 0x%02x\n", - device, c); - err = 0xFF; - goto AI_OUT; - } - - /* write command block */ - ide_output_data_shorts(device, (unsigned short *)ccb, ccblen / 2); - - /* ATAPI Command written wait for completition */ - udelay(5000); /* device must set bsy */ - - mask = ATA_STAT_DRQ | ATA_STAT_BUSY | ATA_STAT_ERR; - /* - * if no data wait for DRQ = 0 BSY = 0 - * if data wait for DRQ = 1 BSY = 0 - */ - res = 0; - if (buflen) - res = ATA_STAT_DRQ; - c = atapi_wait_mask(device, ATAPI_TIME_OUT, mask, res); - if ((c & mask) != res) { - if (c & ATA_STAT_ERR) { - err = (ide_inb(device, ATA_ERROR_REG)) >> 4; - debug("atapi_issue 1 returned sense key %X status %02X\n", - err, c); - } else { - printf("ATAPI_ISSUE: (no DRQ) after sending ccb (%x) status 0x%02x\n", - ccb[0], c); - err = 0xFF; - } - goto AI_OUT; - } - n = ide_inb(device, ATA_CYL_HIGH); - n <<= 8; - n += ide_inb(device, ATA_CYL_LOW); - if (n > buflen) { - printf("ERROR, transfer bytes %d requested only %d\n", n, - buflen); - err = 0xff; - goto AI_OUT; - } - if ((n == 0) && (buflen < 0)) { - printf("ERROR, transfer bytes %d requested %d\n", n, buflen); - err = 0xff; - goto AI_OUT; - } - if (n != buflen) { - debug("WARNING, transfer bytes %d not equal with requested %d\n", - n, buflen); - } - if (n != 0) { /* data transfer */ - debug("ATAPI_ISSUE: %d Bytes to transfer\n", n); - /* we transfer shorts */ - n >>= 1; - /* ok now decide if it is an in or output */ - if ((ide_inb(device, ATA_SECT_CNT) & 0x02) == 0) { - debug("Write to device\n"); - ide_output_data_shorts(device, (unsigned short *)buffer, - n); - } else { - debug("Read from device @ %p shorts %d\n", buffer, n); - ide_input_data_shorts(device, (unsigned short *)buffer, - n); - } - } - udelay(5000); /* seems that some CD ROMs need this... */ - mask = ATA_STAT_BUSY | ATA_STAT_ERR; - res = 0; - c = atapi_wait_mask(device, ATAPI_TIME_OUT, mask, res); - if ((c & ATA_STAT_ERR) == ATA_STAT_ERR) { - err = (ide_inb(device, ATA_ERROR_REG) >> 4); - debug("atapi_issue 2 returned sense key %X status %X\n", err, - c); - } else { - err = 0; - } -AI_OUT: - ide_led(DEVICE_LED(device), 0); /* LED off */ - return err; -} - -/* - * sending the command to atapi_issue. If an status other than good - * returns, an request_sense will be issued - */ - -#define ATAPI_DRIVE_NOT_READY 100 -#define ATAPI_UNIT_ATTN 10 - -unsigned char atapi_issue_autoreq(int device, - unsigned char *ccb, - int ccblen, - unsigned char *buffer, int buflen) -{ - unsigned char sense_data[18], sense_ccb[12]; - unsigned char res, key, asc, ascq; - int notready, unitattn; - - unitattn = ATAPI_UNIT_ATTN; - notready = ATAPI_DRIVE_NOT_READY; - -retry: - res = atapi_issue(device, ccb, ccblen, buffer, buflen); - if (res == 0) - return 0; /* Ok */ - - if (res == 0xFF) - return 0xFF; /* error */ - - debug("(auto_req)atapi_issue returned sense key %X\n", res); - - memset(sense_ccb, 0, sizeof(sense_ccb)); - memset(sense_data, 0, sizeof(sense_data)); - sense_ccb[0] = ATAPI_CMD_REQ_SENSE; - sense_ccb[4] = 18; /* allocation Length */ - - res = atapi_issue(device, sense_ccb, 12, sense_data, 18); - key = (sense_data[2] & 0xF); - asc = (sense_data[12]); - ascq = (sense_data[13]); - - debug("ATAPI_CMD_REQ_SENSE returned %x\n", res); - debug(" Sense page: %02X key %02X ASC %02X ASCQ %02X\n", - sense_data[0], key, asc, ascq); - - if ((key == 0)) - return 0; /* ok device ready */ - - if ((key == 6) || (asc == 0x29) || (asc == 0x28)) { /* Unit Attention */ - if (unitattn-- > 0) { - udelay(200 * 1000); - goto retry; - } - printf("Unit Attention, tried %d\n", ATAPI_UNIT_ATTN); - goto error; - } - if ((asc == 0x4) && (ascq == 0x1)) { - /* not ready, but will be ready soon */ - if (notready-- > 0) { - udelay(200 * 1000); - goto retry; - } - printf("Drive not ready, tried %d times\n", - ATAPI_DRIVE_NOT_READY); - goto error; - } - if (asc == 0x3a) { - debug("Media not present\n"); - goto error; - } - - printf("ERROR: Unknown Sense key %02X ASC %02X ASCQ %02X\n", key, asc, - ascq); -error: - debug("ERROR Sense key %02X ASC %02X ASCQ %02X\n", key, asc, ascq); - return 0xFF; -} - -/* - * atapi_read: - * we transfer only one block per command, since the multiple DRQ per - * command is not yet implemented - */ -#define ATAPI_READ_MAX_BYTES 2048 /* we read max 2kbytes */ -#define ATAPI_READ_BLOCK_SIZE 2048 /* assuming CD part */ -#define ATAPI_READ_MAX_BLOCK (ATAPI_READ_MAX_BYTES/ATAPI_READ_BLOCK_SIZE) - -ulong atapi_read(struct blk_desc *block_dev, lbaint_t blknr, lbaint_t blkcnt, - void *buffer) -{ - int device = block_dev->devnum; - ulong n = 0; - unsigned char ccb[12]; /* Command descriptor block */ - ulong cnt; - - debug("atapi_read dev %d start " LBAF " blocks " LBAF - " buffer at %lX\n", device, blknr, blkcnt, (ulong) buffer); - - do { - if (blkcnt > ATAPI_READ_MAX_BLOCK) - cnt = ATAPI_READ_MAX_BLOCK; - else - cnt = blkcnt; - - ccb[0] = ATAPI_CMD_READ_12; - ccb[1] = 0; /* reserved */ - ccb[2] = (unsigned char) (blknr >> 24) & 0xFF; /* MSB Block */ - ccb[3] = (unsigned char) (blknr >> 16) & 0xFF; /* */ - ccb[4] = (unsigned char) (blknr >> 8) & 0xFF; - ccb[5] = (unsigned char) blknr & 0xFF; /* LSB Block */ - ccb[6] = (unsigned char) (cnt >> 24) & 0xFF; /* MSB Block cnt */ - ccb[7] = (unsigned char) (cnt >> 16) & 0xFF; - ccb[8] = (unsigned char) (cnt >> 8) & 0xFF; - ccb[9] = (unsigned char) cnt & 0xFF; /* LSB Block */ - ccb[10] = 0; /* reserved */ - ccb[11] = 0; /* reserved */ - - if (atapi_issue_autoreq(device, ccb, 12, - (unsigned char *)buffer, - cnt * ATAPI_READ_BLOCK_SIZE) - == 0xFF) { - return n; - } - n += cnt; - blkcnt -= cnt; - blknr += cnt; - buffer += (cnt * ATAPI_READ_BLOCK_SIZE); - } while (blkcnt > 0); - return n; -} - -static void atapi_inquiry(struct blk_desc *dev_desc) -{ - unsigned char ccb[12]; /* Command descriptor block */ - unsigned char iobuf[64]; /* temp buf */ - unsigned char c; - int device; - - device = dev_desc->devnum; - dev_desc->type = DEV_TYPE_UNKNOWN; /* not yet valid */ - dev_desc->block_read = atapi_read; - - memset(ccb, 0, sizeof(ccb)); - memset(iobuf, 0, sizeof(iobuf)); - - ccb[0] = ATAPI_CMD_INQUIRY; - ccb[4] = 40; /* allocation Legnth */ - c = atapi_issue_autoreq(device, ccb, 12, (unsigned char *)iobuf, 40); - - debug("ATAPI_CMD_INQUIRY returned %x\n", c); - if (c != 0) - return; - - /* copy device ident strings */ - ident_cpy((unsigned char *)dev_desc->vendor, &iobuf[8], 8); - ident_cpy((unsigned char *)dev_desc->product, &iobuf[16], 16); - ident_cpy((unsigned char *)dev_desc->revision, &iobuf[32], 5); - - dev_desc->lun = 0; - dev_desc->lba = 0; - dev_desc->blksz = 0; - dev_desc->log2blksz = LOG2_INVALID(typeof(dev_desc->log2blksz)); - dev_desc->type = iobuf[0] & 0x1f; - - if ((iobuf[1] & 0x80) == 0x80) - dev_desc->removable = 1; - else - dev_desc->removable = 0; - - memset(ccb, 0, sizeof(ccb)); - memset(iobuf, 0, sizeof(iobuf)); - ccb[0] = ATAPI_CMD_START_STOP; - ccb[4] = 0x03; /* start */ - - c = atapi_issue_autoreq(device, ccb, 12, (unsigned char *)iobuf, 0); - - debug("ATAPI_CMD_START_STOP returned %x\n", c); - if (c != 0) - return; - - memset(ccb, 0, sizeof(ccb)); - memset(iobuf, 0, sizeof(iobuf)); - c = atapi_issue_autoreq(device, ccb, 12, (unsigned char *)iobuf, 0); - - debug("ATAPI_CMD_UNIT_TEST_READY returned %x\n", c); - if (c != 0) - return; - - memset(ccb, 0, sizeof(ccb)); - memset(iobuf, 0, sizeof(iobuf)); - ccb[0] = ATAPI_CMD_READ_CAP; - c = atapi_issue_autoreq(device, ccb, 12, (unsigned char *)iobuf, 8); - debug("ATAPI_CMD_READ_CAP returned %x\n", c); - if (c != 0) - return; - - debug("Read Cap: LBA %02X%02X%02X%02X blksize %02X%02X%02X%02X\n", - iobuf[0], iobuf[1], iobuf[2], iobuf[3], - iobuf[4], iobuf[5], iobuf[6], iobuf[7]); - - dev_desc->lba = ((unsigned long) iobuf[0] << 24) + - ((unsigned long) iobuf[1] << 16) + - ((unsigned long) iobuf[2] << 8) + ((unsigned long) iobuf[3]); - dev_desc->blksz = ((unsigned long) iobuf[4] << 24) + - ((unsigned long) iobuf[5] << 16) + - ((unsigned long) iobuf[6] << 8) + ((unsigned long) iobuf[7]); - dev_desc->log2blksz = LOG2(dev_desc->blksz); -#ifdef CONFIG_LBA48 - /* ATAPI devices cannot use 48bit addressing (ATA/ATAPI v7) */ - dev_desc->lba48 = 0; -#endif - return; -} - -#endif /* CONFIG_ATAPI */ - -static void ide_ident(struct blk_desc *dev_desc) -{ - unsigned char c; - hd_driveid_t iop; - -#ifdef CONFIG_ATAPI - int retries = 0; -#endif - int device; - - device = dev_desc->devnum; - printf(" Device %d: ", device); - - ide_led(DEVICE_LED(device), 1); /* LED on */ - /* Select device - */ - ide_outb(device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device)); - dev_desc->if_type = IF_TYPE_IDE; -#ifdef CONFIG_ATAPI - - retries = 0; - - /* Warning: This will be tricky to read */ - while (retries <= 1) { - /* check signature */ - if ((ide_inb(device, ATA_SECT_CNT) == 0x01) && - (ide_inb(device, ATA_SECT_NUM) == 0x01) && - (ide_inb(device, ATA_CYL_LOW) == 0x14) && - (ide_inb(device, ATA_CYL_HIGH) == 0xEB)) { - /* ATAPI Signature found */ - dev_desc->if_type = IF_TYPE_ATAPI; - /* - * Start Ident Command - */ - ide_outb(device, ATA_COMMAND, ATAPI_CMD_IDENT); - /* - * Wait for completion - ATAPI devices need more time - * to become ready - */ - c = ide_wait(device, ATAPI_TIME_OUT); - } else -#endif - { - /* - * Start Ident Command - */ - ide_outb(device, ATA_COMMAND, ATA_CMD_IDENT); - - /* - * Wait for completion - */ - c = ide_wait(device, IDE_TIME_OUT); - } - ide_led(DEVICE_LED(device), 0); /* LED off */ - - if (((c & ATA_STAT_DRQ) == 0) || - ((c & (ATA_STAT_FAULT | ATA_STAT_ERR)) != 0)) { -#ifdef CONFIG_ATAPI - { - /* - * Need to soft reset the device - * in case it's an ATAPI... - */ - debug("Retrying...\n"); - ide_outb(device, ATA_DEV_HD, - ATA_LBA | ATA_DEVICE(device)); - udelay(100000); - ide_outb(device, ATA_COMMAND, 0x08); - udelay(500000); /* 500 ms */ - } - /* - * Select device - */ - ide_outb(device, ATA_DEV_HD, - ATA_LBA | ATA_DEVICE(device)); - retries++; -#else - return; -#endif - } -#ifdef CONFIG_ATAPI - else - break; - } /* see above - ugly to read */ - - if (retries == 2) /* Not found */ - return; -#endif - - ide_input_swap_data(device, (ulong *)&iop, ATA_SECTORWORDS); - - ident_cpy((unsigned char *)dev_desc->revision, iop.fw_rev, - sizeof(dev_desc->revision)); - ident_cpy((unsigned char *)dev_desc->vendor, iop.model, - sizeof(dev_desc->vendor)); - ident_cpy((unsigned char *)dev_desc->product, iop.serial_no, - sizeof(dev_desc->product)); -#ifdef __LITTLE_ENDIAN - /* - * firmware revision, model, and serial number have Big Endian Byte - * order in Word. Convert all three to little endian. - * - * See CF+ and CompactFlash Specification Revision 2.0: - * 6.2.1.6: Identify Drive, Table 39 for more details - */ - - strswab(dev_desc->revision); - strswab(dev_desc->vendor); - strswab(dev_desc->product); -#endif /* __LITTLE_ENDIAN */ - - if ((iop.config & 0x0080) == 0x0080) - dev_desc->removable = 1; - else - dev_desc->removable = 0; - -#ifdef CONFIG_ATAPI - if (dev_desc->if_type == IF_TYPE_ATAPI) { - atapi_inquiry(dev_desc); - return; - } -#endif /* CONFIG_ATAPI */ - -#ifdef __BIG_ENDIAN - /* swap shorts */ - dev_desc->lba = (iop.lba_capacity << 16) | (iop.lba_capacity >> 16); -#else /* ! __BIG_ENDIAN */ - /* - * do not swap shorts on little endian - * - * See CF+ and CompactFlash Specification Revision 2.0: - * 6.2.1.6: Identfy Drive, Table 39, Word Address 57-58 for details. - */ - dev_desc->lba = iop.lba_capacity; -#endif /* __BIG_ENDIAN */ - -#ifdef CONFIG_LBA48 - if (iop.command_set_2 & 0x0400) { /* LBA 48 support */ - dev_desc->lba48 = 1; - dev_desc->lba = (unsigned long long) iop.lba48_capacity[0] | - ((unsigned long long) iop.lba48_capacity[1] << 16) | - ((unsigned long long) iop.lba48_capacity[2] << 32) | - ((unsigned long long) iop.lba48_capacity[3] << 48); - } else { - dev_desc->lba48 = 0; - } -#endif /* CONFIG_LBA48 */ - /* assuming HD */ - dev_desc->type = DEV_TYPE_HARDDISK; - dev_desc->blksz = ATA_BLOCKSIZE; - dev_desc->log2blksz = LOG2(dev_desc->blksz); - dev_desc->lun = 0; /* just to fill something in... */ - -#if 0 /* only used to test the powersaving mode, - * if enabled, the drive goes after 5 sec - * in standby mode */ - ide_outb(device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device)); - c = ide_wait(device, IDE_TIME_OUT); - ide_outb(device, ATA_SECT_CNT, 1); - ide_outb(device, ATA_LBA_LOW, 0); - ide_outb(device, ATA_LBA_MID, 0); - ide_outb(device, ATA_LBA_HIGH, 0); - ide_outb(device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device)); - ide_outb(device, ATA_COMMAND, 0xe3); - udelay(50); - c = ide_wait(device, IDE_TIME_OUT); /* can't take over 500 ms */ -#endif -} - -/* ------------------------------------------------------------------------- */ - int do_ide(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) { int rcode = 0; @@ -759,79 +51,41 @@ int do_ide(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) ide_init(); return 0; } else if (strncmp(argv[1], "inf", 3) == 0) { - int i; - - putc('\n'); - - for (i = 0; i < CONFIG_SYS_IDE_MAXDEVICE; ++i) { - if (ide_dev_desc[i].type == DEV_TYPE_UNKNOWN) - continue; /* list only known devices */ - printf("IDE device %d: ", i); - dev_print(&ide_dev_desc[i]); - } + blk_list_devices(IF_TYPE_IDE); return 0; } else if (strncmp(argv[1], "dev", 3) == 0) { - if (curr_device < 0 || - curr_device >= CONFIG_SYS_IDE_MAXDEVICE) { - puts("\nno IDE devices available\n"); - return 1; + if (blk_print_device_num(IF_TYPE_IDE, curr_device)) { + printf("\nno IDE devices available\n"); + return CMD_RET_FAILURE; } - printf("\nIDE device %d: ", curr_device); - dev_print(&ide_dev_desc[curr_device]); + return 0; } else if (strncmp(argv[1], "part", 4) == 0) { - int dev, ok; - - for (ok = 0, dev = 0; - dev < CONFIG_SYS_IDE_MAXDEVICE; - ++dev) { - if (ide_dev_desc[dev].part_type != - PART_TYPE_UNKNOWN) { - ++ok; - if (dev) - putc('\n'); - part_print(&ide_dev_desc[dev]); - } - } - if (!ok) { - puts("\nno IDE devices available\n"); - rcode++; - } - return rcode; + if (blk_list_part(IF_TYPE_IDE)) + printf("\nno IDE devices available\n"); + return 1; } return CMD_RET_USAGE; case 3: if (strncmp(argv[1], "dev", 3) == 0) { int dev = (int)simple_strtoul(argv[2], NULL, 10); - printf("\nIDE device %d: ", dev); - if (dev >= CONFIG_SYS_IDE_MAXDEVICE) { - puts("unknown device\n"); - return 1; + if (!blk_show_device(IF_TYPE_IDE, dev)) { + curr_device = dev; + printf("... is now current device\n"); + } else { + return CMD_RET_FAILURE; } - dev_print(&ide_dev_desc[dev]); - /*ide_print (dev); */ - - if (ide_dev_desc[dev].type == DEV_TYPE_UNKNOWN) - return 1; - - curr_device = dev; - - puts("... is now current device\n"); - return 0; } else if (strncmp(argv[1], "part", 4) == 0) { int dev = (int)simple_strtoul(argv[2], NULL, 10); - if (ide_dev_desc[dev].part_type != PART_TYPE_UNKNOWN) { - part_print(&ide_dev_desc[dev]); - } else { - printf("\nIDE device %d not available\n", - dev); - rcode = 1; + if (blk_print_part_devnum(IF_TYPE_IDE, dev)) { + printf("\nIDE device %d not available\n", dev); + return CMD_RET_FAILURE; } - return rcode; + return 1; } return CMD_RET_USAGE; @@ -841,7 +95,6 @@ int do_ide(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) if (strcmp(argv[1], "read") == 0) { ulong addr = simple_strtoul(argv[2], NULL, 16); ulong cnt = simple_strtoul(argv[4], NULL, 16); - struct blk_desc *dev_desc; ulong n; #ifdef CONFIG_SYS_64BIT_LBA @@ -856,11 +109,8 @@ int do_ide(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) curr_device, blk, cnt); #endif - dev_desc = &ide_dev_desc[curr_device]; - n = blk_dread(dev_desc, blk, cnt, (ulong *)addr); - /* flush cache after read */ - flush_cache(addr, - cnt * ide_dev_desc[curr_device].blksz); + n = blk_read_devnum(IF_TYPE_IDE, curr_device, blk, cnt, + (ulong *)addr); printf("%ld blocks read: %s\n", n, (n == cnt) ? "OK" : "ERROR"); @@ -884,8 +134,8 @@ int do_ide(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) printf("\nIDE write: device %d block # %ld, count %ld...", curr_device, blk, cnt); #endif - n = ide_write(&ide_dev_desc[curr_device], blk, cnt, - (ulong *)addr); + n = blk_write_devnum(IF_TYPE_IDE, curr_device, blk, cnt, + (ulong *)addr); printf("%ld blocks written: %s\n", n, n == cnt ? "OK" : "ERROR"); @@ -906,511 +156,6 @@ int do_diskboot(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) return common_diskboot(cmdtp, "ide", argc, argv); } -/* ------------------------------------------------------------------------- */ - -__weak void ide_led(uchar led, uchar status) -{ -#if defined(CONFIG_IDE_LED) && defined(PER8_BASE) /* required by LED_PORT */ - static uchar led_buffer; /* Buffer for current LED status */ - - uchar *led_port = LED_PORT; - - if (status) /* switch LED on */ - led_buffer |= led; - else /* switch LED off */ - led_buffer &= ~led; - - *led_port = led_buffer; -#endif -} - -/* ------------------------------------------------------------------------- */ - -__weak void ide_outb(int dev, int port, unsigned char val) -{ - debug("ide_outb (dev= %d, port= 0x%x, val= 0x%02x) : @ 0x%08lx\n", - dev, port, val, - (ATA_CURR_BASE(dev) + CONFIG_SYS_ATA_PORT_ADDR(port))); - -#if defined(CONFIG_IDE_AHB) - if (port) { - /* write command */ - ide_write_register(dev, port, val); - } else { - /* write data */ - outb(val, (ATA_CURR_BASE(dev))); - } -#else - outb(val, (ATA_CURR_BASE(dev) + CONFIG_SYS_ATA_PORT_ADDR(port))); -#endif -} - -__weak unsigned char ide_inb(int dev, int port) -{ - uchar val; - -#if defined(CONFIG_IDE_AHB) - val = ide_read_register(dev, port); -#else - val = inb((ATA_CURR_BASE(dev) + CONFIG_SYS_ATA_PORT_ADDR(port))); -#endif - - debug("ide_inb (dev= %d, port= 0x%x) : @ 0x%08lx -> 0x%02x\n", - dev, port, - (ATA_CURR_BASE(dev) + CONFIG_SYS_ATA_PORT_ADDR(port)), val); - return val; -} - -void ide_init(void) -{ - unsigned char c; - int i, bus; - -#ifdef CONFIG_IDE_8xx_PCCARD - extern int ide_devices_found; /* Initialized in check_ide_device() */ -#endif /* CONFIG_IDE_8xx_PCCARD */ - -#ifdef CONFIG_IDE_PREINIT - WATCHDOG_RESET(); - - if (ide_preinit()) { - puts("ide_preinit failed\n"); - return; - } -#endif /* CONFIG_IDE_PREINIT */ - - WATCHDOG_RESET(); - - /* - * Reset the IDE just to be sure. - * Light LED's to show - */ - ide_led((LED_IDE1 | LED_IDE2), 1); /* LED's on */ - - /* ATAPI Drives seems to need a proper IDE Reset */ - ide_reset(); - -#ifdef CONFIG_IDE_INIT_POSTRESET - WATCHDOG_RESET(); - - if (ide_init_postreset()) { - puts("ide_preinit_postreset failed\n"); - return; - } -#endif /* CONFIG_IDE_INIT_POSTRESET */ - - /* - * Wait for IDE to get ready. - * According to spec, this can take up to 31 seconds! - */ - for (bus = 0; bus < CONFIG_SYS_IDE_MAXBUS; ++bus) { - int dev = - bus * (CONFIG_SYS_IDE_MAXDEVICE / - CONFIG_SYS_IDE_MAXBUS); - -#ifdef CONFIG_IDE_8xx_PCCARD - /* Skip non-ide devices from probing */ - if ((ide_devices_found & (1 << bus)) == 0) { - ide_led((LED_IDE1 | LED_IDE2), 0); /* LED's off */ - continue; - } -#endif - printf("Bus %d: ", bus); - - ide_bus_ok[bus] = 0; - - /* Select device - */ - udelay(100000); /* 100 ms */ - ide_outb(dev, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(dev)); - udelay(100000); /* 100 ms */ - i = 0; - do { - udelay(10000); /* 10 ms */ - - c = ide_inb(dev, ATA_STATUS); - i++; - if (i > (ATA_RESET_TIME * 100)) { - puts("** Timeout **\n"); - /* LED's off */ - ide_led((LED_IDE1 | LED_IDE2), 0); - return; - } - if ((i >= 100) && ((i % 100) == 0)) - putc('.'); - - } while (c & ATA_STAT_BUSY); - - if (c & (ATA_STAT_BUSY | ATA_STAT_FAULT)) { - puts("not available "); - debug("Status = 0x%02X ", c); -#ifndef CONFIG_ATAPI /* ATAPI Devices do not set DRDY */ - } else if ((c & ATA_STAT_READY) == 0) { - puts("not available "); - debug("Status = 0x%02X ", c); -#endif - } else { - puts("OK "); - ide_bus_ok[bus] = 1; - } - WATCHDOG_RESET(); - } - - putc('\n'); - - ide_led((LED_IDE1 | LED_IDE2), 0); /* LED's off */ - - curr_device = -1; - for (i = 0; i < CONFIG_SYS_IDE_MAXDEVICE; ++i) { - int led = (IDE_BUS(i) == 0) ? LED_IDE1 : LED_IDE2; - ide_dev_desc[i].type = DEV_TYPE_UNKNOWN; - ide_dev_desc[i].if_type = IF_TYPE_IDE; - ide_dev_desc[i].devnum = i; - ide_dev_desc[i].part_type = PART_TYPE_UNKNOWN; - ide_dev_desc[i].blksz = 0; - ide_dev_desc[i].log2blksz = - LOG2_INVALID(typeof(ide_dev_desc[i].log2blksz)); - ide_dev_desc[i].lba = 0; - ide_dev_desc[i].block_read = ide_read; - ide_dev_desc[i].block_write = ide_write; - if (!ide_bus_ok[IDE_BUS(i)]) - continue; - ide_led(led, 1); /* LED on */ - ide_ident(&ide_dev_desc[i]); - ide_led(led, 0); /* LED off */ - dev_print(&ide_dev_desc[i]); - - if ((ide_dev_desc[i].lba > 0) && (ide_dev_desc[i].blksz > 0)) { - /* initialize partition type */ - part_init(&ide_dev_desc[i]); - if (curr_device < 0) - curr_device = i; - } - } - WATCHDOG_RESET(); -} - -/* ------------------------------------------------------------------------- */ - -#ifdef CONFIG_PARTITIONS -struct blk_desc *ide_get_dev(int dev) -{ - return (dev < CONFIG_SYS_IDE_MAXDEVICE) ? &ide_dev_desc[dev] : NULL; -} -#endif - -/* ------------------------------------------------------------------------- */ - -/* We only need to swap data if we are running on a big endian cpu. */ -#if defined(__LITTLE_ENDIAN) -__weak void ide_input_swap_data(int dev, ulong *sect_buf, int words) -{ - ide_input_data(dev, sect_buf, words); -} -#else -__weak void ide_input_swap_data(int dev, ulong *sect_buf, int words) -{ - volatile ushort *pbuf = - (ushort *)(ATA_CURR_BASE(dev) + ATA_DATA_REG); - ushort *dbuf = (ushort *)sect_buf; - - debug("in input swap data base for read is %lx\n", - (unsigned long) pbuf); - - while (words--) { -#ifdef __MIPS__ - *dbuf++ = swab16p((u16 *)pbuf); - *dbuf++ = swab16p((u16 *)pbuf); -#else - *dbuf++ = ld_le16(pbuf); - *dbuf++ = ld_le16(pbuf); -#endif /* !MIPS */ - } -} -#endif /* __LITTLE_ENDIAN */ - - -#if defined(CONFIG_IDE_SWAP_IO) -__weak void ide_output_data(int dev, const ulong *sect_buf, int words) -{ - ushort *dbuf; - volatile ushort *pbuf; - - pbuf = (ushort *)(ATA_CURR_BASE(dev) + ATA_DATA_REG); - dbuf = (ushort *)sect_buf; - while (words--) { - EIEIO; - *pbuf = *dbuf++; - EIEIO; - *pbuf = *dbuf++; - } -} -#else /* ! CONFIG_IDE_SWAP_IO */ -__weak void ide_output_data(int dev, const ulong *sect_buf, int words) -{ -#if defined(CONFIG_IDE_AHB) - ide_write_data(dev, sect_buf, words); -#else - outsw(ATA_CURR_BASE(dev) + ATA_DATA_REG, sect_buf, words << 1); -#endif -} -#endif /* CONFIG_IDE_SWAP_IO */ - -#if defined(CONFIG_IDE_SWAP_IO) -__weak void ide_input_data(int dev, ulong *sect_buf, int words) -{ - ushort *dbuf; - volatile ushort *pbuf; - - pbuf = (ushort *)(ATA_CURR_BASE(dev) + ATA_DATA_REG); - dbuf = (ushort *)sect_buf; - - debug("in input data base for read is %lx\n", (unsigned long) pbuf); - - while (words--) { - EIEIO; - *dbuf++ = *pbuf; - EIEIO; - *dbuf++ = *pbuf; - } -} -#else /* ! CONFIG_IDE_SWAP_IO */ -__weak void ide_input_data(int dev, ulong *sect_buf, int words) -{ -#if defined(CONFIG_IDE_AHB) - ide_read_data(dev, sect_buf, words); -#else - insw(ATA_CURR_BASE(dev) + ATA_DATA_REG, sect_buf, words << 1); -#endif -} - -#endif /* CONFIG_IDE_SWAP_IO */ - -/* ------------------------------------------------------------------------- */ - -ulong ide_read(struct blk_desc *block_dev, lbaint_t blknr, lbaint_t blkcnt, - void *buffer) -{ - int device = block_dev->devnum; - ulong n = 0; - unsigned char c; - unsigned char pwrsave = 0; /* power save */ - -#ifdef CONFIG_LBA48 - unsigned char lba48 = 0; - - if (blknr & 0x0000fffff0000000ULL) { - /* more than 28 bits used, use 48bit mode */ - lba48 = 1; - } -#endif - debug("ide_read dev %d start " LBAF ", blocks " LBAF " buffer at %lX\n", - device, blknr, blkcnt, (ulong) buffer); - - ide_led(DEVICE_LED(device), 1); /* LED on */ - - /* Select device - */ - ide_outb(device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device)); - c = ide_wait(device, IDE_TIME_OUT); - - if (c & ATA_STAT_BUSY) { - printf("IDE read: device %d not ready\n", device); - goto IDE_READ_E; - } - - /* first check if the drive is in Powersaving mode, if yes, - * increase the timeout value */ - ide_outb(device, ATA_COMMAND, ATA_CMD_CHK_PWR); - udelay(50); - - c = ide_wait(device, IDE_TIME_OUT); /* can't take over 500 ms */ - - if (c & ATA_STAT_BUSY) { - printf("IDE read: device %d not ready\n", device); - goto IDE_READ_E; - } - if ((c & ATA_STAT_ERR) == ATA_STAT_ERR) { - printf("No Powersaving mode %X\n", c); - } else { - c = ide_inb(device, ATA_SECT_CNT); - debug("Powersaving %02X\n", c); - if (c == 0) - pwrsave = 1; - } - - - while (blkcnt-- > 0) { - - c = ide_wait(device, IDE_TIME_OUT); - - if (c & ATA_STAT_BUSY) { - printf("IDE read: device %d not ready\n", device); - break; - } -#ifdef CONFIG_LBA48 - if (lba48) { - /* write high bits */ - ide_outb(device, ATA_SECT_CNT, 0); - ide_outb(device, ATA_LBA_LOW, (blknr >> 24) & 0xFF); -#ifdef CONFIG_SYS_64BIT_LBA - ide_outb(device, ATA_LBA_MID, (blknr >> 32) & 0xFF); - ide_outb(device, ATA_LBA_HIGH, (blknr >> 40) & 0xFF); -#else - ide_outb(device, ATA_LBA_MID, 0); - ide_outb(device, ATA_LBA_HIGH, 0); -#endif - } -#endif - ide_outb(device, ATA_SECT_CNT, 1); - ide_outb(device, ATA_LBA_LOW, (blknr >> 0) & 0xFF); - ide_outb(device, ATA_LBA_MID, (blknr >> 8) & 0xFF); - ide_outb(device, ATA_LBA_HIGH, (blknr >> 16) & 0xFF); - -#ifdef CONFIG_LBA48 - if (lba48) { - ide_outb(device, ATA_DEV_HD, - ATA_LBA | ATA_DEVICE(device)); - ide_outb(device, ATA_COMMAND, ATA_CMD_READ_EXT); - - } else -#endif - { - ide_outb(device, ATA_DEV_HD, ATA_LBA | - ATA_DEVICE(device) | ((blknr >> 24) & 0xF)); - ide_outb(device, ATA_COMMAND, ATA_CMD_READ); - } - - udelay(50); - - if (pwrsave) { - /* may take up to 4 sec */ - c = ide_wait(device, IDE_SPIN_UP_TIME_OUT); - pwrsave = 0; - } else { - /* can't take over 500 ms */ - c = ide_wait(device, IDE_TIME_OUT); - } - - if ((c & (ATA_STAT_DRQ | ATA_STAT_BUSY | ATA_STAT_ERR)) != - ATA_STAT_DRQ) { - printf("Error (no IRQ) dev %d blk " LBAF - ": status %#02x\n", device, blknr, c); - break; - } - - ide_input_data(device, buffer, ATA_SECTORWORDS); - (void) ide_inb(device, ATA_STATUS); /* clear IRQ */ - - ++n; - ++blknr; - buffer += ATA_BLOCKSIZE; - } -IDE_READ_E: - ide_led(DEVICE_LED(device), 0); /* LED off */ - return n; -} - -/* ------------------------------------------------------------------------- */ - - -ulong ide_write(struct blk_desc *block_dev, lbaint_t blknr, lbaint_t blkcnt, - const void *buffer) -{ - int device = block_dev->devnum; - ulong n = 0; - unsigned char c; - -#ifdef CONFIG_LBA48 - unsigned char lba48 = 0; - - if (blknr & 0x0000fffff0000000ULL) { - /* more than 28 bits used, use 48bit mode */ - lba48 = 1; - } -#endif - - ide_led(DEVICE_LED(device), 1); /* LED on */ - - /* Select device - */ - ide_outb(device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device)); - - while (blkcnt-- > 0) { - c = ide_wait(device, IDE_TIME_OUT); - - if (c & ATA_STAT_BUSY) { - printf("IDE read: device %d not ready\n", device); - goto WR_OUT; - } -#ifdef CONFIG_LBA48 - if (lba48) { - /* write high bits */ - ide_outb(device, ATA_SECT_CNT, 0); - ide_outb(device, ATA_LBA_LOW, (blknr >> 24) & 0xFF); -#ifdef CONFIG_SYS_64BIT_LBA - ide_outb(device, ATA_LBA_MID, (blknr >> 32) & 0xFF); - ide_outb(device, ATA_LBA_HIGH, (blknr >> 40) & 0xFF); -#else - ide_outb(device, ATA_LBA_MID, 0); - ide_outb(device, ATA_LBA_HIGH, 0); -#endif - } -#endif - ide_outb(device, ATA_SECT_CNT, 1); - ide_outb(device, ATA_LBA_LOW, (blknr >> 0) & 0xFF); - ide_outb(device, ATA_LBA_MID, (blknr >> 8) & 0xFF); - ide_outb(device, ATA_LBA_HIGH, (blknr >> 16) & 0xFF); - -#ifdef CONFIG_LBA48 - if (lba48) { - ide_outb(device, ATA_DEV_HD, - ATA_LBA | ATA_DEVICE(device)); - ide_outb(device, ATA_COMMAND, ATA_CMD_WRITE_EXT); - - } else -#endif - { - ide_outb(device, ATA_DEV_HD, ATA_LBA | - ATA_DEVICE(device) | ((blknr >> 24) & 0xF)); - ide_outb(device, ATA_COMMAND, ATA_CMD_WRITE); - } - - udelay(50); - - /* can't take over 500 ms */ - c = ide_wait(device, IDE_TIME_OUT); - - if ((c & (ATA_STAT_DRQ | ATA_STAT_BUSY | ATA_STAT_ERR)) != - ATA_STAT_DRQ) { - printf("Error (no IRQ) dev %d blk " LBAF - ": status %#02x\n", device, blknr, c); - goto WR_OUT; - } - - ide_output_data(device, buffer, ATA_SECTORWORDS); - c = ide_inb(device, ATA_STATUS); /* clear IRQ */ - ++n; - ++blknr; - buffer += ATA_BLOCKSIZE; - } -WR_OUT: - ide_led(DEVICE_LED(device), 0); /* LED off */ - return n; -} - -/* ------------------------------------------------------------------------- */ - -#if defined(CONFIG_OF_IDE_FIXUP) -int ide_device_present(int dev) -{ - if (dev >= CONFIG_SYS_IDE_MAXBUS) - return 0; - return ide_dev_desc[dev].type == DEV_TYPE_UNKNOWN ? 0 : 1; -} -#endif -/* ------------------------------------------------------------------------- */ - U_BOOT_CMD(ide, 5, 1, do_ide, "IDE sub-system", "reset - reset IDE controller\n" diff --git a/common/Makefile b/common/Makefile index 397df61016..1df5add325 100644 --- a/common/Makefile +++ b/common/Makefile @@ -134,6 +134,7 @@ obj-y += dlmalloc.o ifdef CONFIG_SYS_MALLOC_F_LEN obj-y += malloc_simple.o endif +obj-$(CONFIG_CMD_IDE) += ide.o obj-y += image.o obj-$(CONFIG_ANDROID_BOOT_IMAGE) += image-android.o obj-$(CONFIG_$(SPL_)OF_LIBFDT) += image-fdt.o diff --git a/common/ide.c b/common/ide.c new file mode 100644 index 0000000000..adc1966efa --- /dev/null +++ b/common/ide.c @@ -0,0 +1,1206 @@ +/* + * (C) Copyright 2000-2011 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include +#include + +#ifdef __PPC__ +# define EIEIO __asm__ volatile ("eieio") +# define SYNC __asm__ volatile ("sync") +#else +# define EIEIO /* nothing */ +# define SYNC /* nothing */ +#endif + +/* Current offset for IDE0 / IDE1 bus access */ +ulong ide_bus_offset[CONFIG_SYS_IDE_MAXBUS] = { +#if defined(CONFIG_SYS_ATA_IDE0_OFFSET) + CONFIG_SYS_ATA_IDE0_OFFSET, +#endif +#if defined(CONFIG_SYS_ATA_IDE1_OFFSET) && (CONFIG_SYS_IDE_MAXBUS > 1) + CONFIG_SYS_ATA_IDE1_OFFSET, +#endif +}; + +static int ide_bus_ok[CONFIG_SYS_IDE_MAXBUS]; + +struct blk_desc ide_dev_desc[CONFIG_SYS_IDE_MAXDEVICE]; + +#define IDE_TIME_OUT 2000 /* 2 sec timeout */ + +#define ATAPI_TIME_OUT 7000 /* 7 sec timeout (5 sec seems to work...) */ + +#define IDE_SPIN_UP_TIME_OUT 5000 /* 5 sec spin-up timeout */ + +#ifndef CONFIG_SYS_ATA_PORT_ADDR +#define CONFIG_SYS_ATA_PORT_ADDR(port) (port) +#endif + +#ifndef CONFIG_IDE_LED /* define LED macros, they are not used anyways */ +# define DEVICE_LED(x) 0 +# define LED_IDE1 1 +# define LED_IDE2 2 +#endif + +#ifdef CONFIG_IDE_RESET +extern void ide_set_reset(int idereset); + +static void ide_reset(void) +{ + int i; + + for (i = 0; i < CONFIG_SYS_IDE_MAXBUS; ++i) + ide_bus_ok[i] = 0; + for (i = 0; i < CONFIG_SYS_IDE_MAXDEVICE; ++i) + ide_dev_desc[i].type = DEV_TYPE_UNKNOWN; + + ide_set_reset(1); /* assert reset */ + + /* the reset signal shall be asserted for et least 25 us */ + udelay(25); + + WATCHDOG_RESET(); + + /* de-assert RESET signal */ + ide_set_reset(0); + + /* wait 250 ms */ + for (i = 0; i < 250; ++i) + udelay(1000); +} +#else +#define ide_reset() /* dummy */ +#endif /* CONFIG_IDE_RESET */ + +/* + * Wait until Busy bit is off, or timeout (in ms) + * Return last status + */ +static uchar ide_wait(int dev, ulong t) +{ + ulong delay = 10 * t; /* poll every 100 us */ + uchar c; + + while ((c = ide_inb(dev, ATA_STATUS)) & ATA_STAT_BUSY) { + udelay(100); + if (delay-- == 0) + break; + } + return c; +} + +/* + * copy src to dest, skipping leading and trailing blanks and null + * terminate the string + * "len" is the size of available memory including the terminating '\0' + */ +static void ident_cpy(unsigned char *dst, unsigned char *src, + unsigned int len) +{ + unsigned char *end, *last; + + last = dst; + end = src + len - 1; + + /* reserve space for '\0' */ + if (len < 2) + goto OUT; + + /* skip leading white space */ + while ((*src) && (src < end) && (*src == ' ')) + ++src; + + /* copy string, omitting trailing white space */ + while ((*src) && (src < end)) { + *dst++ = *src; + if (*src++ != ' ') + last = dst; + } +OUT: + *last = '\0'; +} + +#ifdef CONFIG_ATAPI +/**************************************************************************** + * ATAPI Support + */ + +#if defined(CONFIG_IDE_SWAP_IO) +/* since ATAPI may use commands with not 4 bytes alligned length + * we have our own transfer functions, 2 bytes alligned */ +__weak void ide_output_data_shorts(int dev, ushort *sect_buf, int shorts) +{ + ushort *dbuf; + volatile ushort *pbuf; + + pbuf = (ushort *)(ATA_CURR_BASE(dev) + ATA_DATA_REG); + dbuf = (ushort *)sect_buf; + + debug("in output data shorts base for read is %lx\n", + (unsigned long) pbuf); + + while (shorts--) { + EIEIO; + *pbuf = *dbuf++; + } +} + +__weak void ide_input_data_shorts(int dev, ushort *sect_buf, int shorts) +{ + ushort *dbuf; + volatile ushort *pbuf; + + pbuf = (ushort *)(ATA_CURR_BASE(dev) + ATA_DATA_REG); + dbuf = (ushort *)sect_buf; + + debug("in input data shorts base for read is %lx\n", + (unsigned long) pbuf); + + while (shorts--) { + EIEIO; + *dbuf++ = *pbuf; + } +} + +#else /* ! CONFIG_IDE_SWAP_IO */ +__weak void ide_output_data_shorts(int dev, ushort *sect_buf, int shorts) +{ + outsw(ATA_CURR_BASE(dev) + ATA_DATA_REG, sect_buf, shorts); +} + +__weak void ide_input_data_shorts(int dev, ushort *sect_buf, int shorts) +{ + insw(ATA_CURR_BASE(dev) + ATA_DATA_REG, sect_buf, shorts); +} + +#endif /* CONFIG_IDE_SWAP_IO */ + +/* + * Wait until (Status & mask) == res, or timeout (in ms) + * Return last status + * This is used since some ATAPI CD ROMs clears their Busy Bit first + * and then they set their DRQ Bit + */ +static uchar atapi_wait_mask(int dev, ulong t, uchar mask, uchar res) +{ + ulong delay = 10 * t; /* poll every 100 us */ + uchar c; + + /* prevents to read the status before valid */ + c = ide_inb(dev, ATA_DEV_CTL); + + while (((c = ide_inb(dev, ATA_STATUS)) & mask) != res) { + /* break if error occurs (doesn't make sense to wait more) */ + if ((c & ATA_STAT_ERR) == ATA_STAT_ERR) + break; + udelay(100); + if (delay-- == 0) + break; + } + return c; +} + +/* + * issue an atapi command + */ +unsigned char atapi_issue(int device, unsigned char *ccb, int ccblen, + unsigned char *buffer, int buflen) +{ + unsigned char c, err, mask, res; + int n; + + ide_led(DEVICE_LED(device), 1); /* LED on */ + + /* Select device + */ + mask = ATA_STAT_BUSY | ATA_STAT_DRQ; + res = 0; + ide_outb(device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device)); + c = atapi_wait_mask(device, ATAPI_TIME_OUT, mask, res); + if ((c & mask) != res) { + printf("ATAPI_ISSUE: device %d not ready status %X\n", device, + c); + err = 0xFF; + goto AI_OUT; + } + /* write taskfile */ + ide_outb(device, ATA_ERROR_REG, 0); /* no DMA, no overlaped */ + ide_outb(device, ATA_SECT_CNT, 0); + ide_outb(device, ATA_SECT_NUM, 0); + ide_outb(device, ATA_CYL_LOW, (unsigned char) (buflen & 0xFF)); + ide_outb(device, ATA_CYL_HIGH, + (unsigned char) ((buflen >> 8) & 0xFF)); + ide_outb(device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device)); + + ide_outb(device, ATA_COMMAND, ATAPI_CMD_PACKET); + udelay(50); + + mask = ATA_STAT_DRQ | ATA_STAT_BUSY | ATA_STAT_ERR; + res = ATA_STAT_DRQ; + c = atapi_wait_mask(device, ATAPI_TIME_OUT, mask, res); + + if ((c & mask) != res) { /* DRQ must be 1, BSY 0 */ + printf("ATAPI_ISSUE: Error (no IRQ) before sending ccb dev %d status 0x%02x\n", + device, c); + err = 0xFF; + goto AI_OUT; + } + + /* write command block */ + ide_output_data_shorts(device, (unsigned short *)ccb, ccblen / 2); + + /* ATAPI Command written wait for completition */ + udelay(5000); /* device must set bsy */ + + mask = ATA_STAT_DRQ | ATA_STAT_BUSY | ATA_STAT_ERR; + /* + * if no data wait for DRQ = 0 BSY = 0 + * if data wait for DRQ = 1 BSY = 0 + */ + res = 0; + if (buflen) + res = ATA_STAT_DRQ; + c = atapi_wait_mask(device, ATAPI_TIME_OUT, mask, res); + if ((c & mask) != res) { + if (c & ATA_STAT_ERR) { + err = (ide_inb(device, ATA_ERROR_REG)) >> 4; + debug("atapi_issue 1 returned sense key %X status %02X\n", + err, c); + } else { + printf("ATAPI_ISSUE: (no DRQ) after sending ccb (%x) status 0x%02x\n", + ccb[0], c); + err = 0xFF; + } + goto AI_OUT; + } + n = ide_inb(device, ATA_CYL_HIGH); + n <<= 8; + n += ide_inb(device, ATA_CYL_LOW); + if (n > buflen) { + printf("ERROR, transfer bytes %d requested only %d\n", n, + buflen); + err = 0xff; + goto AI_OUT; + } + if ((n == 0) && (buflen < 0)) { + printf("ERROR, transfer bytes %d requested %d\n", n, buflen); + err = 0xff; + goto AI_OUT; + } + if (n != buflen) { + debug("WARNING, transfer bytes %d not equal with requested %d\n", + n, buflen); + } + if (n != 0) { /* data transfer */ + debug("ATAPI_ISSUE: %d Bytes to transfer\n", n); + /* we transfer shorts */ + n >>= 1; + /* ok now decide if it is an in or output */ + if ((ide_inb(device, ATA_SECT_CNT) & 0x02) == 0) { + debug("Write to device\n"); + ide_output_data_shorts(device, (unsigned short *)buffer, + n); + } else { + debug("Read from device @ %p shorts %d\n", buffer, n); + ide_input_data_shorts(device, (unsigned short *)buffer, + n); + } + } + udelay(5000); /* seems that some CD ROMs need this... */ + mask = ATA_STAT_BUSY | ATA_STAT_ERR; + res = 0; + c = atapi_wait_mask(device, ATAPI_TIME_OUT, mask, res); + if ((c & ATA_STAT_ERR) == ATA_STAT_ERR) { + err = (ide_inb(device, ATA_ERROR_REG) >> 4); + debug("atapi_issue 2 returned sense key %X status %X\n", err, + c); + } else { + err = 0; + } +AI_OUT: + ide_led(DEVICE_LED(device), 0); /* LED off */ + return err; +} + +/* + * sending the command to atapi_issue. If an status other than good + * returns, an request_sense will be issued + */ + +#define ATAPI_DRIVE_NOT_READY 100 +#define ATAPI_UNIT_ATTN 10 + +unsigned char atapi_issue_autoreq(int device, + unsigned char *ccb, + int ccblen, + unsigned char *buffer, int buflen) +{ + unsigned char sense_data[18], sense_ccb[12]; + unsigned char res, key, asc, ascq; + int notready, unitattn; + + unitattn = ATAPI_UNIT_ATTN; + notready = ATAPI_DRIVE_NOT_READY; + +retry: + res = atapi_issue(device, ccb, ccblen, buffer, buflen); + if (res == 0) + return 0; /* Ok */ + + if (res == 0xFF) + return 0xFF; /* error */ + + debug("(auto_req)atapi_issue returned sense key %X\n", res); + + memset(sense_ccb, 0, sizeof(sense_ccb)); + memset(sense_data, 0, sizeof(sense_data)); + sense_ccb[0] = ATAPI_CMD_REQ_SENSE; + sense_ccb[4] = 18; /* allocation Length */ + + res = atapi_issue(device, sense_ccb, 12, sense_data, 18); + key = (sense_data[2] & 0xF); + asc = (sense_data[12]); + ascq = (sense_data[13]); + + debug("ATAPI_CMD_REQ_SENSE returned %x\n", res); + debug(" Sense page: %02X key %02X ASC %02X ASCQ %02X\n", + sense_data[0], key, asc, ascq); + + if ((key == 0)) + return 0; /* ok device ready */ + + if ((key == 6) || (asc == 0x29) || (asc == 0x28)) { /* Unit Attention */ + if (unitattn-- > 0) { + udelay(200 * 1000); + goto retry; + } + printf("Unit Attention, tried %d\n", ATAPI_UNIT_ATTN); + goto error; + } + if ((asc == 0x4) && (ascq == 0x1)) { + /* not ready, but will be ready soon */ + if (notready-- > 0) { + udelay(200 * 1000); + goto retry; + } + printf("Drive not ready, tried %d times\n", + ATAPI_DRIVE_NOT_READY); + goto error; + } + if (asc == 0x3a) { + debug("Media not present\n"); + goto error; + } + + printf("ERROR: Unknown Sense key %02X ASC %02X ASCQ %02X\n", key, asc, + ascq); +error: + debug("ERROR Sense key %02X ASC %02X ASCQ %02X\n", key, asc, ascq); + return 0xFF; +} + +/* + * atapi_read: + * we transfer only one block per command, since the multiple DRQ per + * command is not yet implemented + */ +#define ATAPI_READ_MAX_BYTES 2048 /* we read max 2kbytes */ +#define ATAPI_READ_BLOCK_SIZE 2048 /* assuming CD part */ +#define ATAPI_READ_MAX_BLOCK (ATAPI_READ_MAX_BYTES/ATAPI_READ_BLOCK_SIZE) + +ulong atapi_read(struct blk_desc *block_dev, lbaint_t blknr, lbaint_t blkcnt, + void *buffer) +{ + int device = block_dev->devnum; + ulong n = 0; + unsigned char ccb[12]; /* Command descriptor block */ + ulong cnt; + + debug("atapi_read dev %d start " LBAF " blocks " LBAF + " buffer at %lX\n", device, blknr, blkcnt, (ulong) buffer); + + do { + if (blkcnt > ATAPI_READ_MAX_BLOCK) + cnt = ATAPI_READ_MAX_BLOCK; + else + cnt = blkcnt; + + ccb[0] = ATAPI_CMD_READ_12; + ccb[1] = 0; /* reserved */ + ccb[2] = (unsigned char) (blknr >> 24) & 0xFF; /* MSB Block */ + ccb[3] = (unsigned char) (blknr >> 16) & 0xFF; /* */ + ccb[4] = (unsigned char) (blknr >> 8) & 0xFF; + ccb[5] = (unsigned char) blknr & 0xFF; /* LSB Block */ + ccb[6] = (unsigned char) (cnt >> 24) & 0xFF; /* MSB Block cnt */ + ccb[7] = (unsigned char) (cnt >> 16) & 0xFF; + ccb[8] = (unsigned char) (cnt >> 8) & 0xFF; + ccb[9] = (unsigned char) cnt & 0xFF; /* LSB Block */ + ccb[10] = 0; /* reserved */ + ccb[11] = 0; /* reserved */ + + if (atapi_issue_autoreq(device, ccb, 12, + (unsigned char *)buffer, + cnt * ATAPI_READ_BLOCK_SIZE) + == 0xFF) { + return n; + } + n += cnt; + blkcnt -= cnt; + blknr += cnt; + buffer += (cnt * ATAPI_READ_BLOCK_SIZE); + } while (blkcnt > 0); + return n; +} + +static void atapi_inquiry(struct blk_desc *dev_desc) +{ + unsigned char ccb[12]; /* Command descriptor block */ + unsigned char iobuf[64]; /* temp buf */ + unsigned char c; + int device; + + device = dev_desc->devnum; + dev_desc->type = DEV_TYPE_UNKNOWN; /* not yet valid */ + dev_desc->block_read = atapi_read; + + memset(ccb, 0, sizeof(ccb)); + memset(iobuf, 0, sizeof(iobuf)); + + ccb[0] = ATAPI_CMD_INQUIRY; + ccb[4] = 40; /* allocation Legnth */ + c = atapi_issue_autoreq(device, ccb, 12, (unsigned char *)iobuf, 40); + + debug("ATAPI_CMD_INQUIRY returned %x\n", c); + if (c != 0) + return; + + /* copy device ident strings */ + ident_cpy((unsigned char *)dev_desc->vendor, &iobuf[8], 8); + ident_cpy((unsigned char *)dev_desc->product, &iobuf[16], 16); + ident_cpy((unsigned char *)dev_desc->revision, &iobuf[32], 5); + + dev_desc->lun = 0; + dev_desc->lba = 0; + dev_desc->blksz = 0; + dev_desc->log2blksz = LOG2_INVALID(typeof(dev_desc->log2blksz)); + dev_desc->type = iobuf[0] & 0x1f; + + if ((iobuf[1] & 0x80) == 0x80) + dev_desc->removable = 1; + else + dev_desc->removable = 0; + + memset(ccb, 0, sizeof(ccb)); + memset(iobuf, 0, sizeof(iobuf)); + ccb[0] = ATAPI_CMD_START_STOP; + ccb[4] = 0x03; /* start */ + + c = atapi_issue_autoreq(device, ccb, 12, (unsigned char *)iobuf, 0); + + debug("ATAPI_CMD_START_STOP returned %x\n", c); + if (c != 0) + return; + + memset(ccb, 0, sizeof(ccb)); + memset(iobuf, 0, sizeof(iobuf)); + c = atapi_issue_autoreq(device, ccb, 12, (unsigned char *)iobuf, 0); + + debug("ATAPI_CMD_UNIT_TEST_READY returned %x\n", c); + if (c != 0) + return; + + memset(ccb, 0, sizeof(ccb)); + memset(iobuf, 0, sizeof(iobuf)); + ccb[0] = ATAPI_CMD_READ_CAP; + c = atapi_issue_autoreq(device, ccb, 12, (unsigned char *)iobuf, 8); + debug("ATAPI_CMD_READ_CAP returned %x\n", c); + if (c != 0) + return; + + debug("Read Cap: LBA %02X%02X%02X%02X blksize %02X%02X%02X%02X\n", + iobuf[0], iobuf[1], iobuf[2], iobuf[3], + iobuf[4], iobuf[5], iobuf[6], iobuf[7]); + + dev_desc->lba = ((unsigned long) iobuf[0] << 24) + + ((unsigned long) iobuf[1] << 16) + + ((unsigned long) iobuf[2] << 8) + ((unsigned long) iobuf[3]); + dev_desc->blksz = ((unsigned long) iobuf[4] << 24) + + ((unsigned long) iobuf[5] << 16) + + ((unsigned long) iobuf[6] << 8) + ((unsigned long) iobuf[7]); + dev_desc->log2blksz = LOG2(dev_desc->blksz); +#ifdef CONFIG_LBA48 + /* ATAPI devices cannot use 48bit addressing (ATA/ATAPI v7) */ + dev_desc->lba48 = 0; +#endif + return; +} + +#endif /* CONFIG_ATAPI */ + +static void ide_ident(struct blk_desc *dev_desc) +{ + unsigned char c; + hd_driveid_t iop; + +#ifdef CONFIG_ATAPI + int retries = 0; +#endif + int device; + + device = dev_desc->devnum; + printf(" Device %d: ", device); + + ide_led(DEVICE_LED(device), 1); /* LED on */ + /* Select device + */ + ide_outb(device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device)); + dev_desc->if_type = IF_TYPE_IDE; +#ifdef CONFIG_ATAPI + + retries = 0; + + /* Warning: This will be tricky to read */ + while (retries <= 1) { + /* check signature */ + if ((ide_inb(device, ATA_SECT_CNT) == 0x01) && + (ide_inb(device, ATA_SECT_NUM) == 0x01) && + (ide_inb(device, ATA_CYL_LOW) == 0x14) && + (ide_inb(device, ATA_CYL_HIGH) == 0xEB)) { + /* ATAPI Signature found */ + dev_desc->if_type = IF_TYPE_ATAPI; + /* + * Start Ident Command + */ + ide_outb(device, ATA_COMMAND, ATAPI_CMD_IDENT); + /* + * Wait for completion - ATAPI devices need more time + * to become ready + */ + c = ide_wait(device, ATAPI_TIME_OUT); + } else +#endif + { + /* + * Start Ident Command + */ + ide_outb(device, ATA_COMMAND, ATA_CMD_IDENT); + + /* + * Wait for completion + */ + c = ide_wait(device, IDE_TIME_OUT); + } + ide_led(DEVICE_LED(device), 0); /* LED off */ + + if (((c & ATA_STAT_DRQ) == 0) || + ((c & (ATA_STAT_FAULT | ATA_STAT_ERR)) != 0)) { +#ifdef CONFIG_ATAPI + { + /* + * Need to soft reset the device + * in case it's an ATAPI... + */ + debug("Retrying...\n"); + ide_outb(device, ATA_DEV_HD, + ATA_LBA | ATA_DEVICE(device)); + udelay(100000); + ide_outb(device, ATA_COMMAND, 0x08); + udelay(500000); /* 500 ms */ + } + /* + * Select device + */ + ide_outb(device, ATA_DEV_HD, + ATA_LBA | ATA_DEVICE(device)); + retries++; +#else + return; +#endif + } +#ifdef CONFIG_ATAPI + else + break; + } /* see above - ugly to read */ + + if (retries == 2) /* Not found */ + return; +#endif + + ide_input_swap_data(device, (ulong *)&iop, ATA_SECTORWORDS); + + ident_cpy((unsigned char *)dev_desc->revision, iop.fw_rev, + sizeof(dev_desc->revision)); + ident_cpy((unsigned char *)dev_desc->vendor, iop.model, + sizeof(dev_desc->vendor)); + ident_cpy((unsigned char *)dev_desc->product, iop.serial_no, + sizeof(dev_desc->product)); +#ifdef __LITTLE_ENDIAN + /* + * firmware revision, model, and serial number have Big Endian Byte + * order in Word. Convert all three to little endian. + * + * See CF+ and CompactFlash Specification Revision 2.0: + * 6.2.1.6: Identify Drive, Table 39 for more details + */ + + strswab(dev_desc->revision); + strswab(dev_desc->vendor); + strswab(dev_desc->product); +#endif /* __LITTLE_ENDIAN */ + + if ((iop.config & 0x0080) == 0x0080) + dev_desc->removable = 1; + else + dev_desc->removable = 0; + +#ifdef CONFIG_ATAPI + if (dev_desc->if_type == IF_TYPE_ATAPI) { + atapi_inquiry(dev_desc); + return; + } +#endif /* CONFIG_ATAPI */ + +#ifdef __BIG_ENDIAN + /* swap shorts */ + dev_desc->lba = (iop.lba_capacity << 16) | (iop.lba_capacity >> 16); +#else /* ! __BIG_ENDIAN */ + /* + * do not swap shorts on little endian + * + * See CF+ and CompactFlash Specification Revision 2.0: + * 6.2.1.6: Identfy Drive, Table 39, Word Address 57-58 for details. + */ + dev_desc->lba = iop.lba_capacity; +#endif /* __BIG_ENDIAN */ + +#ifdef CONFIG_LBA48 + if (iop.command_set_2 & 0x0400) { /* LBA 48 support */ + dev_desc->lba48 = 1; + dev_desc->lba = (unsigned long long) iop.lba48_capacity[0] | + ((unsigned long long) iop.lba48_capacity[1] << 16) | + ((unsigned long long) iop.lba48_capacity[2] << 32) | + ((unsigned long long) iop.lba48_capacity[3] << 48); + } else { + dev_desc->lba48 = 0; + } +#endif /* CONFIG_LBA48 */ + /* assuming HD */ + dev_desc->type = DEV_TYPE_HARDDISK; + dev_desc->blksz = ATA_BLOCKSIZE; + dev_desc->log2blksz = LOG2(dev_desc->blksz); + dev_desc->lun = 0; /* just to fill something in... */ + +#if 0 /* only used to test the powersaving mode, + * if enabled, the drive goes after 5 sec + * in standby mode */ + ide_outb(device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device)); + c = ide_wait(device, IDE_TIME_OUT); + ide_outb(device, ATA_SECT_CNT, 1); + ide_outb(device, ATA_LBA_LOW, 0); + ide_outb(device, ATA_LBA_MID, 0); + ide_outb(device, ATA_LBA_HIGH, 0); + ide_outb(device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device)); + ide_outb(device, ATA_COMMAND, 0xe3); + udelay(50); + c = ide_wait(device, IDE_TIME_OUT); /* can't take over 500 ms */ +#endif +} + +__weak void ide_led(uchar led, uchar status) +{ +#if defined(CONFIG_IDE_LED) && defined(PER8_BASE) /* required by LED_PORT */ + static uchar led_buffer; /* Buffer for current LED status */ + + uchar *led_port = LED_PORT; + + if (status) /* switch LED on */ + led_buffer |= led; + else /* switch LED off */ + led_buffer &= ~led; + + *led_port = led_buffer; +#endif +} + +__weak void ide_outb(int dev, int port, unsigned char val) +{ + debug("ide_outb (dev= %d, port= 0x%x, val= 0x%02x) : @ 0x%08lx\n", + dev, port, val, + (ATA_CURR_BASE(dev) + CONFIG_SYS_ATA_PORT_ADDR(port))); + +#if defined(CONFIG_IDE_AHB) + if (port) { + /* write command */ + ide_write_register(dev, port, val); + } else { + /* write data */ + outb(val, (ATA_CURR_BASE(dev))); + } +#else + outb(val, (ATA_CURR_BASE(dev) + CONFIG_SYS_ATA_PORT_ADDR(port))); +#endif +} + +__weak unsigned char ide_inb(int dev, int port) +{ + uchar val; + +#if defined(CONFIG_IDE_AHB) + val = ide_read_register(dev, port); +#else + val = inb((ATA_CURR_BASE(dev) + CONFIG_SYS_ATA_PORT_ADDR(port))); +#endif + + debug("ide_inb (dev= %d, port= 0x%x) : @ 0x%08lx -> 0x%02x\n", + dev, port, + (ATA_CURR_BASE(dev) + CONFIG_SYS_ATA_PORT_ADDR(port)), val); + return val; +} + +void ide_init(void) +{ + unsigned char c; + int i, bus; + +#ifdef CONFIG_IDE_8xx_PCCARD + extern int ide_devices_found; /* Initialized in check_ide_device() */ +#endif /* CONFIG_IDE_8xx_PCCARD */ + +#ifdef CONFIG_IDE_PREINIT + WATCHDOG_RESET(); + + if (ide_preinit()) { + puts("ide_preinit failed\n"); + return; + } +#endif /* CONFIG_IDE_PREINIT */ + + WATCHDOG_RESET(); + + /* + * Reset the IDE just to be sure. + * Light LED's to show + */ + ide_led((LED_IDE1 | LED_IDE2), 1); /* LED's on */ + + /* ATAPI Drives seems to need a proper IDE Reset */ + ide_reset(); + +#ifdef CONFIG_IDE_INIT_POSTRESET + WATCHDOG_RESET(); + + if (ide_init_postreset()) { + puts("ide_preinit_postreset failed\n"); + return; + } +#endif /* CONFIG_IDE_INIT_POSTRESET */ + + /* + * Wait for IDE to get ready. + * According to spec, this can take up to 31 seconds! + */ + for (bus = 0; bus < CONFIG_SYS_IDE_MAXBUS; ++bus) { + int dev = + bus * (CONFIG_SYS_IDE_MAXDEVICE / + CONFIG_SYS_IDE_MAXBUS); + +#ifdef CONFIG_IDE_8xx_PCCARD + /* Skip non-ide devices from probing */ + if ((ide_devices_found & (1 << bus)) == 0) { + ide_led((LED_IDE1 | LED_IDE2), 0); /* LED's off */ + continue; + } +#endif + printf("Bus %d: ", bus); + + ide_bus_ok[bus] = 0; + + /* Select device + */ + udelay(100000); /* 100 ms */ + ide_outb(dev, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(dev)); + udelay(100000); /* 100 ms */ + i = 0; + do { + udelay(10000); /* 10 ms */ + + c = ide_inb(dev, ATA_STATUS); + i++; + if (i > (ATA_RESET_TIME * 100)) { + puts("** Timeout **\n"); + /* LED's off */ + ide_led((LED_IDE1 | LED_IDE2), 0); + return; + } + if ((i >= 100) && ((i % 100) == 0)) + putc('.'); + + } while (c & ATA_STAT_BUSY); + + if (c & (ATA_STAT_BUSY | ATA_STAT_FAULT)) { + puts("not available "); + debug("Status = 0x%02X ", c); +#ifndef CONFIG_ATAPI /* ATAPI Devices do not set DRDY */ + } else if ((c & ATA_STAT_READY) == 0) { + puts("not available "); + debug("Status = 0x%02X ", c); +#endif + } else { + puts("OK "); + ide_bus_ok[bus] = 1; + } + WATCHDOG_RESET(); + } + + putc('\n'); + + ide_led((LED_IDE1 | LED_IDE2), 0); /* LED's off */ + + for (i = 0; i < CONFIG_SYS_IDE_MAXDEVICE; ++i) { + int led = (IDE_BUS(i) == 0) ? LED_IDE1 : LED_IDE2; + ide_dev_desc[i].type = DEV_TYPE_UNKNOWN; + ide_dev_desc[i].if_type = IF_TYPE_IDE; + ide_dev_desc[i].devnum = i; + ide_dev_desc[i].part_type = PART_TYPE_UNKNOWN; + ide_dev_desc[i].blksz = 0; + ide_dev_desc[i].log2blksz = + LOG2_INVALID(typeof(ide_dev_desc[i].log2blksz)); + ide_dev_desc[i].lba = 0; + ide_dev_desc[i].block_read = ide_read; + ide_dev_desc[i].block_write = ide_write; + if (!ide_bus_ok[IDE_BUS(i)]) + continue; + ide_led(led, 1); /* LED on */ + ide_ident(&ide_dev_desc[i]); + ide_led(led, 0); /* LED off */ + dev_print(&ide_dev_desc[i]); + + if ((ide_dev_desc[i].lba > 0) && (ide_dev_desc[i].blksz > 0)) { + /* initialize partition type */ + part_init(&ide_dev_desc[i]); + } + } + WATCHDOG_RESET(); +} + +#ifdef CONFIG_PARTITIONS +struct blk_desc *ide_get_dev(int dev) +{ + return (dev < CONFIG_SYS_IDE_MAXDEVICE) ? &ide_dev_desc[dev] : NULL; +} +#endif + +/* We only need to swap data if we are running on a big endian cpu. */ +#if defined(__LITTLE_ENDIAN) +__weak void ide_input_swap_data(int dev, ulong *sect_buf, int words) +{ + ide_input_data(dev, sect_buf, words); +} +#else +__weak void ide_input_swap_data(int dev, ulong *sect_buf, int words) +{ + volatile ushort *pbuf = + (ushort *)(ATA_CURR_BASE(dev) + ATA_DATA_REG); + ushort *dbuf = (ushort *)sect_buf; + + debug("in input swap data base for read is %lx\n", + (unsigned long) pbuf); + + while (words--) { +#ifdef __MIPS__ + *dbuf++ = swab16p((u16 *)pbuf); + *dbuf++ = swab16p((u16 *)pbuf); +#else + *dbuf++ = ld_le16(pbuf); + *dbuf++ = ld_le16(pbuf); +#endif /* !MIPS */ + } +} +#endif /* __LITTLE_ENDIAN */ + + +#if defined(CONFIG_IDE_SWAP_IO) +__weak void ide_output_data(int dev, const ulong *sect_buf, int words) +{ + ushort *dbuf; + volatile ushort *pbuf; + + pbuf = (ushort *)(ATA_CURR_BASE(dev) + ATA_DATA_REG); + dbuf = (ushort *)sect_buf; + while (words--) { + EIEIO; + *pbuf = *dbuf++; + EIEIO; + *pbuf = *dbuf++; + } +} +#else /* ! CONFIG_IDE_SWAP_IO */ +__weak void ide_output_data(int dev, const ulong *sect_buf, int words) +{ +#if defined(CONFIG_IDE_AHB) + ide_write_data(dev, sect_buf, words); +#else + outsw(ATA_CURR_BASE(dev) + ATA_DATA_REG, sect_buf, words << 1); +#endif +} +#endif /* CONFIG_IDE_SWAP_IO */ + +#if defined(CONFIG_IDE_SWAP_IO) +__weak void ide_input_data(int dev, ulong *sect_buf, int words) +{ + ushort *dbuf; + volatile ushort *pbuf; + + pbuf = (ushort *)(ATA_CURR_BASE(dev) + ATA_DATA_REG); + dbuf = (ushort *)sect_buf; + + debug("in input data base for read is %lx\n", (unsigned long) pbuf); + + while (words--) { + EIEIO; + *dbuf++ = *pbuf; + EIEIO; + *dbuf++ = *pbuf; + } +} +#else /* ! CONFIG_IDE_SWAP_IO */ +__weak void ide_input_data(int dev, ulong *sect_buf, int words) +{ +#if defined(CONFIG_IDE_AHB) + ide_read_data(dev, sect_buf, words); +#else + insw(ATA_CURR_BASE(dev) + ATA_DATA_REG, sect_buf, words << 1); +#endif +} + +#endif /* CONFIG_IDE_SWAP_IO */ + +ulong ide_read(struct blk_desc *block_dev, lbaint_t blknr, lbaint_t blkcnt, + void *buffer) +{ + int device = block_dev->devnum; + ulong n = 0; + unsigned char c; + unsigned char pwrsave = 0; /* power save */ + +#ifdef CONFIG_LBA48 + unsigned char lba48 = 0; + + if (blknr & 0x0000fffff0000000ULL) { + /* more than 28 bits used, use 48bit mode */ + lba48 = 1; + } +#endif + debug("ide_read dev %d start " LBAF ", blocks " LBAF " buffer at %lX\n", + device, blknr, blkcnt, (ulong) buffer); + + ide_led(DEVICE_LED(device), 1); /* LED on */ + + /* Select device + */ + ide_outb(device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device)); + c = ide_wait(device, IDE_TIME_OUT); + + if (c & ATA_STAT_BUSY) { + printf("IDE read: device %d not ready\n", device); + goto IDE_READ_E; + } + + /* first check if the drive is in Powersaving mode, if yes, + * increase the timeout value */ + ide_outb(device, ATA_COMMAND, ATA_CMD_CHK_PWR); + udelay(50); + + c = ide_wait(device, IDE_TIME_OUT); /* can't take over 500 ms */ + + if (c & ATA_STAT_BUSY) { + printf("IDE read: device %d not ready\n", device); + goto IDE_READ_E; + } + if ((c & ATA_STAT_ERR) == ATA_STAT_ERR) { + printf("No Powersaving mode %X\n", c); + } else { + c = ide_inb(device, ATA_SECT_CNT); + debug("Powersaving %02X\n", c); + if (c == 0) + pwrsave = 1; + } + + + while (blkcnt-- > 0) { + c = ide_wait(device, IDE_TIME_OUT); + + if (c & ATA_STAT_BUSY) { + printf("IDE read: device %d not ready\n", device); + break; + } +#ifdef CONFIG_LBA48 + if (lba48) { + /* write high bits */ + ide_outb(device, ATA_SECT_CNT, 0); + ide_outb(device, ATA_LBA_LOW, (blknr >> 24) & 0xFF); +#ifdef CONFIG_SYS_64BIT_LBA + ide_outb(device, ATA_LBA_MID, (blknr >> 32) & 0xFF); + ide_outb(device, ATA_LBA_HIGH, (blknr >> 40) & 0xFF); +#else + ide_outb(device, ATA_LBA_MID, 0); + ide_outb(device, ATA_LBA_HIGH, 0); +#endif + } +#endif + ide_outb(device, ATA_SECT_CNT, 1); + ide_outb(device, ATA_LBA_LOW, (blknr >> 0) & 0xFF); + ide_outb(device, ATA_LBA_MID, (blknr >> 8) & 0xFF); + ide_outb(device, ATA_LBA_HIGH, (blknr >> 16) & 0xFF); + +#ifdef CONFIG_LBA48 + if (lba48) { + ide_outb(device, ATA_DEV_HD, + ATA_LBA | ATA_DEVICE(device)); + ide_outb(device, ATA_COMMAND, ATA_CMD_READ_EXT); + + } else +#endif + { + ide_outb(device, ATA_DEV_HD, ATA_LBA | + ATA_DEVICE(device) | ((blknr >> 24) & 0xF)); + ide_outb(device, ATA_COMMAND, ATA_CMD_READ); + } + + udelay(50); + + if (pwrsave) { + /* may take up to 4 sec */ + c = ide_wait(device, IDE_SPIN_UP_TIME_OUT); + pwrsave = 0; + } else { + /* can't take over 500 ms */ + c = ide_wait(device, IDE_TIME_OUT); + } + + if ((c & (ATA_STAT_DRQ | ATA_STAT_BUSY | ATA_STAT_ERR)) != + ATA_STAT_DRQ) { + printf("Error (no IRQ) dev %d blk " LBAF + ": status %#02x\n", device, blknr, c); + break; + } + + ide_input_data(device, buffer, ATA_SECTORWORDS); + (void) ide_inb(device, ATA_STATUS); /* clear IRQ */ + + ++n; + ++blknr; + buffer += ATA_BLOCKSIZE; + } +IDE_READ_E: + ide_led(DEVICE_LED(device), 0); /* LED off */ + return n; +} + +ulong ide_write(struct blk_desc *block_dev, lbaint_t blknr, lbaint_t blkcnt, + const void *buffer) +{ + int device = block_dev->devnum; + ulong n = 0; + unsigned char c; + +#ifdef CONFIG_LBA48 + unsigned char lba48 = 0; + + if (blknr & 0x0000fffff0000000ULL) { + /* more than 28 bits used, use 48bit mode */ + lba48 = 1; + } +#endif + + ide_led(DEVICE_LED(device), 1); /* LED on */ + + /* Select device + */ + ide_outb(device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device)); + + while (blkcnt-- > 0) { + c = ide_wait(device, IDE_TIME_OUT); + + if (c & ATA_STAT_BUSY) { + printf("IDE read: device %d not ready\n", device); + goto WR_OUT; + } +#ifdef CONFIG_LBA48 + if (lba48) { + /* write high bits */ + ide_outb(device, ATA_SECT_CNT, 0); + ide_outb(device, ATA_LBA_LOW, (blknr >> 24) & 0xFF); +#ifdef CONFIG_SYS_64BIT_LBA + ide_outb(device, ATA_LBA_MID, (blknr >> 32) & 0xFF); + ide_outb(device, ATA_LBA_HIGH, (blknr >> 40) & 0xFF); +#else + ide_outb(device, ATA_LBA_MID, 0); + ide_outb(device, ATA_LBA_HIGH, 0); +#endif + } +#endif + ide_outb(device, ATA_SECT_CNT, 1); + ide_outb(device, ATA_LBA_LOW, (blknr >> 0) & 0xFF); + ide_outb(device, ATA_LBA_MID, (blknr >> 8) & 0xFF); + ide_outb(device, ATA_LBA_HIGH, (blknr >> 16) & 0xFF); + +#ifdef CONFIG_LBA48 + if (lba48) { + ide_outb(device, ATA_DEV_HD, + ATA_LBA | ATA_DEVICE(device)); + ide_outb(device, ATA_COMMAND, ATA_CMD_WRITE_EXT); + + } else +#endif + { + ide_outb(device, ATA_DEV_HD, ATA_LBA | + ATA_DEVICE(device) | ((blknr >> 24) & 0xF)); + ide_outb(device, ATA_COMMAND, ATA_CMD_WRITE); + } + + udelay(50); + + /* can't take over 500 ms */ + c = ide_wait(device, IDE_TIME_OUT); + + if ((c & (ATA_STAT_DRQ | ATA_STAT_BUSY | ATA_STAT_ERR)) != + ATA_STAT_DRQ) { + printf("Error (no IRQ) dev %d blk " LBAF + ": status %#02x\n", device, blknr, c); + goto WR_OUT; + } + + ide_output_data(device, buffer, ATA_SECTORWORDS); + c = ide_inb(device, ATA_STATUS); /* clear IRQ */ + ++n; + ++blknr; + buffer += ATA_BLOCKSIZE; + } +WR_OUT: + ide_led(DEVICE_LED(device), 0); /* LED off */ + return n; +} + +#if defined(CONFIG_OF_IDE_FIXUP) +int ide_device_present(int dev) +{ + if (dev >= CONFIG_SYS_IDE_MAXBUS) + return 0; + return ide_dev_desc[dev].type == DEV_TYPE_UNKNOWN ? 0 : 1; +} +#endif + +U_BOOT_LEGACY_BLK(ide) = { + .if_typename = "ide", + .if_type = IF_TYPE_IDE, + .max_devs = CONFIG_SYS_IDE_MAXDEVICE, + .desc = ide_dev_desc, +}; From d97dc8a0e6d38d11848ee78669639324edc0df01 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 1 May 2016 11:36:11 -0600 Subject: [PATCH 059/162] dm: sata: Separate the non-command code into its own file At present the SATA command code includes both the command-processing code and the core SATA functions and data structures. Separate the latter into its own file, adding functions as needed to avoid the command code accessing data structures directly. With this commit: - All CONFIG option are referenced from the non-command code - The concept of a 'current SATA device' is confined to the command code This will make it easier to convert this code to driver model. Signed-off-by: Simon Glass --- cmd/sata.c | 138 +++++++----------------------------------------- common/Makefile | 1 + common/sata.c | 86 ++++++++++++++++++++++++++++++ 3 files changed, 107 insertions(+), 118 deletions(-) create mode 100644 common/sata.c diff --git a/cmd/sata.c b/cmd/sata.c index b1a64d9969..d18b5233e6 100644 --- a/cmd/sata.c +++ b/cmd/sata.c @@ -16,70 +16,6 @@ #include static int sata_curr_device = -1; -struct blk_desc sata_dev_desc[CONFIG_SYS_SATA_MAX_DEVICE]; - -static unsigned long sata_bread(struct blk_desc *block_dev, lbaint_t start, - lbaint_t blkcnt, void *dst) -{ - return sata_read(block_dev->devnum, start, blkcnt, dst); -} - -static unsigned long sata_bwrite(struct blk_desc *block_dev, lbaint_t start, - lbaint_t blkcnt, const void *buffer) -{ - return sata_write(block_dev->devnum, start, blkcnt, buffer); -} - -int __sata_initialize(void) -{ - int rc; - int i; - - for (i = 0; i < CONFIG_SYS_SATA_MAX_DEVICE; i++) { - memset(&sata_dev_desc[i], 0, sizeof(struct blk_desc)); - sata_dev_desc[i].if_type = IF_TYPE_SATA; - sata_dev_desc[i].devnum = i; - sata_dev_desc[i].part_type = PART_TYPE_UNKNOWN; - sata_dev_desc[i].type = DEV_TYPE_HARDDISK; - sata_dev_desc[i].lba = 0; - sata_dev_desc[i].blksz = 512; - sata_dev_desc[i].log2blksz = LOG2(sata_dev_desc[i].blksz); - sata_dev_desc[i].block_read = sata_bread; - sata_dev_desc[i].block_write = sata_bwrite; - - rc = init_sata(i); - if (!rc) { - rc = scan_sata(i); - if (!rc && (sata_dev_desc[i].lba > 0) && - (sata_dev_desc[i].blksz > 0)) - part_init(&sata_dev_desc[i]); - } - } - sata_curr_device = 0; - return rc; -} -int sata_initialize(void) __attribute__((weak,alias("__sata_initialize"))); - -__weak int __sata_stop(void) -{ - int i, err = 0; - - for (i = 0; i < CONFIG_SYS_SATA_MAX_DEVICE; i++) - err |= reset_sata(i); - - if (err) - printf("Could not reset some SATA devices\n"); - - return err; -} -int sata_stop(void) __attribute__((weak, alias("__sata_stop"))); - -#ifdef CONFIG_PARTITIONS -struct blk_desc *sata_get_dev(int dev) -{ - return (dev < CONFIG_SYS_SATA_MAX_DEVICE) ? &sata_dev_desc[dev] : NULL; -} -#endif static int do_sata(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { @@ -106,70 +42,39 @@ static int do_sata(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) return CMD_RET_USAGE; case 2: if (strncmp(argv[1], "inf", 3) == 0) { - int i; - - putc('\n'); - for (i = 0; i < CONFIG_SYS_SATA_MAX_DEVICE; ++i) { - if (sata_dev_desc[i].type == DEV_TYPE_UNKNOWN) - continue; - printf("SATA device %d: ", i); - dev_print(&sata_dev_desc[i]); - } + blk_list_devices(IF_TYPE_SATA); return 0; } else if (strncmp(argv[1], "dev", 3) == 0) { - if (sata_curr_device < 0 || - sata_curr_device >= CONFIG_SYS_SATA_MAX_DEVICE) { - puts("\nno SATA devices available\n"); - return 1; + if (blk_print_device_num(IF_TYPE_SATA, + sata_curr_device)) { + printf("\nno SATA devices available\n"); + return CMD_RET_FAILURE; } - printf("\nSATA device %d: ", sata_curr_device); - dev_print(&sata_dev_desc[sata_curr_device]); return 0; } else if (strncmp(argv[1], "part", 4) == 0) { - int dev, ok; - - for (ok = 0, dev = 0; dev < CONFIG_SYS_SATA_MAX_DEVICE; ++dev) { - if (sata_dev_desc[dev].part_type != PART_TYPE_UNKNOWN) { - ++ok; - if (dev) - putc ('\n'); - part_print(&sata_dev_desc[dev]); - } - } - if (!ok) { + if (blk_list_part(IF_TYPE_SATA)) puts("\nno SATA devices available\n"); - rc ++; - } - return rc; + return 0; } return CMD_RET_USAGE; case 3: if (strncmp(argv[1], "dev", 3) == 0) { int dev = (int)simple_strtoul(argv[2], NULL, 10); - printf("\nSATA device %d: ", dev); - if (dev >= CONFIG_SYS_SATA_MAX_DEVICE) { - puts ("unknown device\n"); - return 1; + if (!blk_show_device(IF_TYPE_SATA, dev)) { + sata_curr_device = dev; + printf("... is now current device\n"); + } else { + return CMD_RET_FAILURE; } - dev_print(&sata_dev_desc[dev]); - - if (sata_dev_desc[dev].type == DEV_TYPE_UNKNOWN) - return 1; - - sata_curr_device = dev; - - puts("... is now current device\n"); - return 0; } else if (strncmp(argv[1], "part", 4) == 0) { int dev = (int)simple_strtoul(argv[2], NULL, 10); - if (sata_dev_desc[dev].part_type != PART_TYPE_UNKNOWN) { - part_print(&sata_dev_desc[dev]); - } else { - printf("\nSATA device %d not available\n", dev); - rc = 1; + if (blk_print_part_devnum(IF_TYPE_SATA, dev)) { + printf("\nSATA device %d not available\n", + dev); + return CMD_RET_FAILURE; } return rc; } @@ -185,11 +90,8 @@ static int do_sata(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) printf("\nSATA read: device %d block # %ld, count %ld ... ", sata_curr_device, blk, cnt); - n = blk_dread(&sata_dev_desc[sata_curr_device], - blk, cnt, (u32 *)addr); - - /* flush cache after read */ - flush_cache(addr, cnt * sata_dev_desc[sata_curr_device].blksz); + n = blk_read_devnum(IF_TYPE_SATA, sata_curr_device, blk, + cnt, (ulong *)addr); printf("%ld blocks read: %s\n", n, (n==cnt) ? "OK" : "ERROR"); @@ -204,8 +106,8 @@ static int do_sata(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) printf("\nSATA write: device %d block # %ld, count %ld ... ", sata_curr_device, blk, cnt); - n = blk_dwrite(&sata_dev_desc[sata_curr_device], - blk, cnt, (u32 *)addr); + n = blk_write_devnum(IF_TYPE_SATA, sata_curr_device, + blk, cnt, (ulong *)addr); printf("%ld blocks written: %s\n", n, (n == cnt) ? "OK" : "ERROR"); diff --git a/common/Makefile b/common/Makefile index 1df5add325..f9b26b7bbe 100644 --- a/common/Makefile +++ b/common/Makefile @@ -84,6 +84,7 @@ obj-$(CONFIG_LCD_ROTATION) += lcd_console_rotation.o obj-$(CONFIG_LCD_DT_SIMPLEFB) += lcd_simplefb.o obj-$(CONFIG_LYNXKDI) += lynxkdi.o obj-$(CONFIG_MENU) += menu.o +obj-$(CONFIG_CMD_SATA) += sata.o obj-$(CONFIG_SCSI) += scsi.o obj-$(CONFIG_UPDATE_TFTP) += update.o obj-$(CONFIG_DFU_TFTP) += update.o diff --git a/common/sata.c b/common/sata.c new file mode 100644 index 0000000000..1d52fcb2dc --- /dev/null +++ b/common/sata.c @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2000-2005, DENX Software Engineering + * Wolfgang Denk + * Copyright (C) Procsys. All rights reserved. + * Mushtaq Khan + * + * Copyright (C) 2008 Freescale Semiconductor, Inc. + * Dave Liu + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include + +struct blk_desc sata_dev_desc[CONFIG_SYS_SATA_MAX_DEVICE]; + +#ifdef CONFIG_PARTITIONS +struct blk_desc *sata_get_dev(int dev) +{ + return (dev < CONFIG_SYS_SATA_MAX_DEVICE) ? &sata_dev_desc[dev] : NULL; +} +#endif + +static unsigned long sata_bread(struct blk_desc *block_dev, lbaint_t start, + lbaint_t blkcnt, void *dst) +{ + return sata_read(block_dev->devnum, start, blkcnt, dst); +} + +static unsigned long sata_bwrite(struct blk_desc *block_dev, lbaint_t start, + lbaint_t blkcnt, const void *buffer) +{ + return sata_write(block_dev->devnum, start, blkcnt, buffer); +} + +int __sata_initialize(void) +{ + int rc; + int i; + + for (i = 0; i < CONFIG_SYS_SATA_MAX_DEVICE; i++) { + memset(&sata_dev_desc[i], 0, sizeof(struct blk_desc)); + sata_dev_desc[i].if_type = IF_TYPE_SATA; + sata_dev_desc[i].devnum = i; + sata_dev_desc[i].part_type = PART_TYPE_UNKNOWN; + sata_dev_desc[i].type = DEV_TYPE_HARDDISK; + sata_dev_desc[i].lba = 0; + sata_dev_desc[i].blksz = 512; + sata_dev_desc[i].log2blksz = LOG2(sata_dev_desc[i].blksz); + sata_dev_desc[i].block_read = sata_bread; + sata_dev_desc[i].block_write = sata_bwrite; + + rc = init_sata(i); + if (!rc) { + rc = scan_sata(i); + if (!rc && sata_dev_desc[i].lba > 0 && + sata_dev_desc[i].blksz > 0) + part_init(&sata_dev_desc[i]); + } + } + + return rc; +} +int sata_initialize(void) __attribute__((weak, alias("__sata_initialize"))); + +__weak int __sata_stop(void) +{ + int i, err = 0; + + for (i = 0; i < CONFIG_SYS_SATA_MAX_DEVICE; i++) + err |= reset_sata(i); + + if (err) + printf("Could not reset some SATA devices\n"); + + return err; +} +int sata_stop(void) __attribute__((weak, alias("__sata_stop"))); + +U_BOOT_LEGACY_BLK(sata) = { + .if_typename = "sata", + .if_type = IF_TYPE_SATA, + .max_devs = CONFIG_SYS_SATA_MAX_DEVICE, + .desc = sata_dev_desc, +}; From a6331fa83cb4a1557df4acfa4214d556f4596904 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 1 May 2016 11:36:12 -0600 Subject: [PATCH 060/162] dm: disk: Use legacy block driver info for block device access Instead of calling xx_get_dev() functions for each interface type, use the new legacy block driver which can provide the device through its interface. Signed-off-by: Simon Glass --- disk/part.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/disk/part.c b/disk/part.c index 2613bff22c..f055c74aa8 100644 --- a/disk/part.c +++ b/disk/part.c @@ -72,7 +72,6 @@ static struct part_driver *part_driver_lookup_type(int part_type) static struct blk_desc *get_dev_hwpart(const char *ifname, int dev, int hwpart) { const struct block_drvr *drvr = block_drvr; - struct blk_desc* (*reloc_get_dev)(int dev); int (*select_hwpart)(int dev_num, int hwpart); char *name; int ret; @@ -86,16 +85,16 @@ static struct blk_desc *get_dev_hwpart(const char *ifname, int dev, int hwpart) #endif while (drvr->name) { name = drvr->name; - reloc_get_dev = drvr->get_dev; select_hwpart = drvr->select_hwpart; #ifdef CONFIG_NEEDS_MANUAL_RELOC name += gd->reloc_off; - reloc_get_dev += gd->reloc_off; if (select_hwpart) select_hwpart += gd->reloc_off; #endif if (strncmp(ifname, name, strlen(name)) == 0) { - struct blk_desc *dev_desc = reloc_get_dev(dev); + struct blk_desc *dev_desc; + + dev_desc = blk_get_devnum_by_typename(name, dev); if (!dev_desc) return NULL; if (hwpart == 0 && !select_hwpart) From 57ebf67bad82da0b3ade1728fb39a64d1c29822f Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 1 May 2016 11:36:13 -0600 Subject: [PATCH 061/162] dm: usb: Drop the get_dev() function This function is implemented by the legacy block functions now. Drop it. Signed-off-by: Simon Glass --- board/cm5200/fwupdate.c | 2 +- cmd/usb.c | 16 ++++++++++------ common/spl/spl_usb.c | 2 +- common/usb_storage.c | 17 ----------------- disk/part.c | 2 +- drivers/Makefile | 1 + include/part.h | 2 -- include/usb.h | 1 - 8 files changed, 14 insertions(+), 29 deletions(-) diff --git a/board/cm5200/fwupdate.c b/board/cm5200/fwupdate.c index 2ed90de9d5..4740c8394c 100644 --- a/board/cm5200/fwupdate.c +++ b/board/cm5200/fwupdate.c @@ -105,7 +105,7 @@ static int load_rescue_image(ulong addr) /* Detect storage device */ for (devno = 0; devno < USB_MAX_STOR_DEV; devno++) { - stor_dev = usb_stor_get_dev(devno); + stor_dev = blk_get_devnum_by_type(IF_TYPE_USB, devno); if (stor_dev->type != DEV_TYPE_UNKNOWN) break; } diff --git a/cmd/usb.c b/cmd/usb.c index f1a7debdf3..b83d3233b7 100644 --- a/cmd/usb.c +++ b/cmd/usb.c @@ -723,7 +723,8 @@ static int do_usb(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) int devno, ok = 0; if (argc == 2) { for (devno = 0; ; ++devno) { - stor_dev = usb_stor_get_dev(devno); + stor_dev = blk_get_devnum_by_type(IF_TYPE_USB, + devno); if (stor_dev == NULL) break; if (stor_dev->type != DEV_TYPE_UNKNOWN) { @@ -736,7 +737,7 @@ static int do_usb(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) } } else { devno = simple_strtoul(argv[2], NULL, 16); - stor_dev = usb_stor_get_dev(devno); + stor_dev = blk_get_devnum_by_type(IF_TYPE_USB, devno); if (stor_dev != NULL && stor_dev->type != DEV_TYPE_UNKNOWN) { ok++; @@ -762,7 +763,8 @@ static int do_usb(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) unsigned long n; printf("\nUSB read: device %d block # %ld, count %ld" " ... ", usb_stor_curr_dev, blk, cnt); - stor_dev = usb_stor_get_dev(usb_stor_curr_dev); + stor_dev = blk_get_devnum_by_type(IF_TYPE_USB, + usb_stor_curr_dev); n = blk_dread(stor_dev, blk, cnt, (ulong *)addr); printf("%ld blocks read: %s\n", n, (n == cnt) ? "OK" : "ERROR"); @@ -783,7 +785,8 @@ static int do_usb(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) unsigned long n; printf("\nUSB write: device %d block # %ld, count %ld" " ... ", usb_stor_curr_dev, blk, cnt); - stor_dev = usb_stor_get_dev(usb_stor_curr_dev); + stor_dev = blk_get_devnum_by_type(IF_TYPE_USB, + usb_stor_curr_dev); n = blk_dwrite(stor_dev, blk, cnt, (ulong *)addr); printf("%ld blocks write: %s\n", n, (n == cnt) ? "OK" : "ERROR"); @@ -796,7 +799,7 @@ static int do_usb(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) if (argc == 3) { int dev = (int)simple_strtoul(argv[2], NULL, 10); printf("\nUSB device %d: ", dev); - stor_dev = usb_stor_get_dev(dev); + stor_dev = blk_get_devnum_by_type(IF_TYPE_USB, dev); if (stor_dev == NULL) { printf("unknown device\n"); return 1; @@ -810,7 +813,8 @@ static int do_usb(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) return 0; } else { printf("\nUSB device %d: ", usb_stor_curr_dev); - stor_dev = usb_stor_get_dev(usb_stor_curr_dev); + stor_dev = blk_get_devnum_by_type(IF_TYPE_USB, + usb_stor_curr_dev); dev_print(stor_dev); if (stor_dev->type == DEV_TYPE_UNKNOWN) return 1; diff --git a/common/spl/spl_usb.c b/common/spl/spl_usb.c index c42848e6fc..04fa66758c 100644 --- a/common/spl/spl_usb.c +++ b/common/spl/spl_usb.c @@ -39,7 +39,7 @@ int spl_usb_load_image(void) #ifdef CONFIG_USB_STORAGE /* try to recognize storage devices immediately */ usb_stor_curr_dev = usb_stor_scan(1); - stor_dev = usb_stor_get_dev(usb_stor_curr_dev); + stor_dev = blk_get_devnum_by_type(IF_TYPE_USB, usb_stor_curr_dev); if (!stor_dev) return -ENODEV; #endif diff --git a/common/usb_storage.c b/common/usb_storage.c index 80bf3db5d0..f2da3a3cad 100644 --- a/common/usb_storage.c +++ b/common/usb_storage.c @@ -136,23 +136,6 @@ static unsigned long usb_stor_write(struct blk_desc *block_dev, lbaint_t blknr, #endif void uhci_show_temp_int_td(void); -#ifdef CONFIG_PARTITIONS -struct blk_desc *usb_stor_get_dev(int index) -{ -#ifdef CONFIG_BLK - struct udevice *dev; - int ret; - - ret = blk_get_device(IF_TYPE_USB, index, &dev); - if (ret) - return NULL; - return dev_get_uclass_platdata(dev); -#else - return (index < usb_max_devs) ? &usb_dev_desc[index] : NULL; -#endif -} -#endif - static void usb_show_progress(void) { debug("."); diff --git a/disk/part.c b/disk/part.c index f055c74aa8..1b33928cc5 100644 --- a/disk/part.c +++ b/disk/part.c @@ -32,7 +32,7 @@ const struct block_drvr block_drvr[] = { { .name = "scsi", .get_dev = scsi_get_dev, }, #endif #if defined(CONFIG_CMD_USB) && defined(CONFIG_USB_STORAGE) - { .name = "usb", .get_dev = usb_stor_get_dev, }, + { .name = "usb", }, #endif #if defined(CONFIG_MMC) { diff --git a/drivers/Makefile b/drivers/Makefile index 6900097e79..696b3ac51b 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -36,6 +36,7 @@ obj-$(CONFIG_SPL_WATCHDOG_SUPPORT) += watchdog/ obj-$(CONFIG_SPL_USB_HOST_SUPPORT) += usb/host/ obj-$(CONFIG_OMAP_USB_PHY) += usb/phy/ obj-$(CONFIG_SPL_SATA_SUPPORT) += block/ +obj-$(CONFIG_SPL_USB_HOST_SUPPORT) += block/ else diff --git a/include/part.h b/include/part.h index e3811c68de..f206910970 100644 --- a/include/part.h +++ b/include/part.h @@ -76,7 +76,6 @@ struct blk_desc *blk_get_dev(const char *ifname, int dev); struct blk_desc *ide_get_dev(int dev); struct blk_desc *sata_get_dev(int dev); struct blk_desc *scsi_get_dev(int dev); -struct blk_desc *usb_stor_get_dev(int dev); struct blk_desc *mmc_get_dev(int dev); /** @@ -178,7 +177,6 @@ static inline struct blk_desc *blk_get_dev(const char *ifname, int dev) static inline struct blk_desc *ide_get_dev(int dev) { return NULL; } static inline struct blk_desc *sata_get_dev(int dev) { return NULL; } static inline struct blk_desc *scsi_get_dev(int dev) { return NULL; } -static inline struct blk_desc *usb_stor_get_dev(int dev) { return NULL; } static inline struct blk_desc *mmc_get_dev(int dev) { return NULL; } static inline int mmc_select_hwpart(int dev_num, int hwpart) { return -1; } static inline struct blk_desc *systemace_get_dev(int dev) { return NULL; } diff --git a/include/usb.h b/include/usb.h index 5adad36838..02a0ccdd77 100644 --- a/include/usb.h +++ b/include/usb.h @@ -228,7 +228,6 @@ int board_usb_cleanup(int index, enum usb_init_type init); #ifdef CONFIG_USB_STORAGE #define USB_MAX_STOR_DEV 7 -struct blk_desc *usb_stor_get_dev(int index); int usb_stor_scan(int mode); int usb_stor_info(void); From 74001a2570ccbc120366e66dd40e8c66e3a6820c Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 1 May 2016 11:36:14 -0600 Subject: [PATCH 062/162] dm: ide: Drop the get_dev() function This function is implemented by the legacy block functions now. Drop it. Signed-off-by: Simon Glass --- common/ide.c | 7 ------- disk/part.c | 2 +- include/part.h | 2 -- 3 files changed, 1 insertion(+), 10 deletions(-) diff --git a/common/ide.c b/common/ide.c index adc1966efa..5dc90d45ec 100644 --- a/common/ide.c +++ b/common/ide.c @@ -890,13 +890,6 @@ void ide_init(void) WATCHDOG_RESET(); } -#ifdef CONFIG_PARTITIONS -struct blk_desc *ide_get_dev(int dev) -{ - return (dev < CONFIG_SYS_IDE_MAXDEVICE) ? &ide_dev_desc[dev] : NULL; -} -#endif - /* We only need to swap data if we are running on a big endian cpu. */ #if defined(__LITTLE_ENDIAN) __weak void ide_input_swap_data(int dev, ulong *sect_buf, int words) diff --git a/disk/part.c b/disk/part.c index 1b33928cc5..bf224b2c52 100644 --- a/disk/part.c +++ b/disk/part.c @@ -23,7 +23,7 @@ const struct block_drvr block_drvr[] = { #if defined(CONFIG_CMD_IDE) - { .name = "ide", .get_dev = ide_get_dev, }, + { .name = "ide", }, #endif #if defined(CONFIG_CMD_SATA) {.name = "sata", .get_dev = sata_get_dev, }, diff --git a/include/part.h b/include/part.h index f206910970..f09b794d61 100644 --- a/include/part.h +++ b/include/part.h @@ -73,7 +73,6 @@ typedef struct disk_partition { * error occurred. */ struct blk_desc *blk_get_dev(const char *ifname, int dev); -struct blk_desc *ide_get_dev(int dev); struct blk_desc *sata_get_dev(int dev); struct blk_desc *scsi_get_dev(int dev); struct blk_desc *mmc_get_dev(int dev); @@ -174,7 +173,6 @@ extern const struct block_drvr block_drvr[]; #else static inline struct blk_desc *blk_get_dev(const char *ifname, int dev) { return NULL; } -static inline struct blk_desc *ide_get_dev(int dev) { return NULL; } static inline struct blk_desc *sata_get_dev(int dev) { return NULL; } static inline struct blk_desc *scsi_get_dev(int dev) { return NULL; } static inline struct blk_desc *mmc_get_dev(int dev) { return NULL; } From 3c457f4d2e47cc91385abe15d3c825d0ce1a2b6f Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 1 May 2016 11:36:15 -0600 Subject: [PATCH 063/162] dm: mmc: Drop the get_dev() function This function is implemented by the legacy block functions now. Drop it. Signed-off-by: Simon Glass --- cmd/mmc.c | 2 +- disk/part.c | 1 - drivers/mmc/mmc.c | 16 ++-------------- include/part.h | 2 -- 4 files changed, 3 insertions(+), 18 deletions(-) diff --git a/cmd/mmc.c b/cmd/mmc.c index c5454bf2e1..4f251870ee 100644 --- a/cmd/mmc.c +++ b/cmd/mmc.c @@ -432,7 +432,7 @@ static int do_mmc_part(cmd_tbl_t *cmdtp, int flag, if (!mmc) return CMD_RET_FAILURE; - mmc_dev = mmc_get_dev(curr_device); + mmc_dev = blk_get_devnum_by_type(IF_TYPE_MMC, curr_device); if (mmc_dev != NULL && mmc_dev->type != DEV_TYPE_UNKNOWN) { part_print(mmc_dev); return CMD_RET_SUCCESS; diff --git a/disk/part.c b/disk/part.c index bf224b2c52..e70bef5aab 100644 --- a/disk/part.c +++ b/disk/part.c @@ -37,7 +37,6 @@ const struct block_drvr block_drvr[] = { #if defined(CONFIG_MMC) { .name = "mmc", - .get_dev = mmc_get_dev, .select_hwpart = mmc_select_hwpart, }, #endif diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c index 024368c727..185d7b2a8e 100644 --- a/drivers/mmc/mmc.c +++ b/drivers/mmc/mmc.c @@ -1582,7 +1582,7 @@ void mmc_destroy(struct mmc *mmc) free(mmc); } -static int mmc_get_devp(int dev, struct blk_desc **descp) +static int mmc_get_dev(int dev, struct blk_desc **descp) { struct mmc *mmc = find_mmc_device(dev); int ret; @@ -1598,18 +1598,6 @@ static int mmc_get_devp(int dev, struct blk_desc **descp) return 0; } -#ifdef CONFIG_PARTITIONS -struct blk_desc *mmc_get_dev(int dev) -{ - struct blk_desc *desc; - - if (mmc_get_devp(dev, &desc)) - return NULL; - - return desc; -} -#endif - /* board-specific MMC power initializations. */ __weak void board_mmc_power_init(void) { @@ -1987,5 +1975,5 @@ U_BOOT_LEGACY_BLK(mmc) = { .if_typename = "mmc", .if_type = IF_TYPE_MMC, .max_devs = -1, - .get_dev = mmc_get_devp, + .get_dev = mmc_get_dev, }; diff --git a/include/part.h b/include/part.h index f09b794d61..1535930b90 100644 --- a/include/part.h +++ b/include/part.h @@ -75,7 +75,6 @@ typedef struct disk_partition { struct blk_desc *blk_get_dev(const char *ifname, int dev); struct blk_desc *sata_get_dev(int dev); struct blk_desc *scsi_get_dev(int dev); -struct blk_desc *mmc_get_dev(int dev); /** * mmc_select_hwpart() - Select the MMC hardware partiion on an MMC device @@ -175,7 +174,6 @@ static inline struct blk_desc *blk_get_dev(const char *ifname, int dev) { return NULL; } static inline struct blk_desc *sata_get_dev(int dev) { return NULL; } static inline struct blk_desc *scsi_get_dev(int dev) { return NULL; } -static inline struct blk_desc *mmc_get_dev(int dev) { return NULL; } static inline int mmc_select_hwpart(int dev_num, int hwpart) { return -1; } static inline struct blk_desc *systemace_get_dev(int dev) { return NULL; } static inline struct blk_desc *mg_disk_get_dev(int dev) { return NULL; } From edd82ab3547e27b4c1ab1ee7e620f982db9126ad Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 1 May 2016 11:36:16 -0600 Subject: [PATCH 064/162] dm: scsi: Drop the get_dev() function This function is implemented by the legacy block functions now. Drop it. Signed-off-by: Simon Glass --- common/scsi.c | 7 ------- common/spl/spl_sata.c | 2 +- disk/part.c | 2 +- include/part.h | 2 -- 4 files changed, 2 insertions(+), 11 deletions(-) diff --git a/common/scsi.c b/common/scsi.c index a336a10753..5b6531f01b 100644 --- a/common/scsi.c +++ b/common/scsi.c @@ -327,13 +327,6 @@ void scsi_init(void) } #endif -#ifdef CONFIG_PARTITIONS -struct blk_desc *scsi_get_dev(int dev) -{ - return (dev < CONFIG_SYS_SCSI_MAX_DEVICE) ? &scsi_dev_desc[dev] : NULL; -} -#endif - /* copy src to dest, skipping leading and trailing blanks * and null terminate the string */ diff --git a/common/spl/spl_sata.c b/common/spl/spl_sata.c index 1719946ec5..9d8cc7c2dd 100644 --- a/common/spl/spl_sata.c +++ b/common/spl/spl_sata.c @@ -34,7 +34,7 @@ int spl_sata_load_image(void) } else { /* try to recognize storage devices immediately */ scsi_scan(0); - stor_dev = scsi_get_dev(0); + stor_dev = blk_get_devnum_by_type(IF_TYPE_SCSI, 0); if (!stor_dev) return -ENODEV; } diff --git a/disk/part.c b/disk/part.c index e70bef5aab..67cb6c0c0b 100644 --- a/disk/part.c +++ b/disk/part.c @@ -29,7 +29,7 @@ const struct block_drvr block_drvr[] = { {.name = "sata", .get_dev = sata_get_dev, }, #endif #if defined(CONFIG_SCSI) - { .name = "scsi", .get_dev = scsi_get_dev, }, + { .name = "scsi", }, #endif #if defined(CONFIG_CMD_USB) && defined(CONFIG_USB_STORAGE) { .name = "usb", }, diff --git a/include/part.h b/include/part.h index 1535930b90..ecb049f9a8 100644 --- a/include/part.h +++ b/include/part.h @@ -74,7 +74,6 @@ typedef struct disk_partition { */ struct blk_desc *blk_get_dev(const char *ifname, int dev); struct blk_desc *sata_get_dev(int dev); -struct blk_desc *scsi_get_dev(int dev); /** * mmc_select_hwpart() - Select the MMC hardware partiion on an MMC device @@ -173,7 +172,6 @@ extern const struct block_drvr block_drvr[]; static inline struct blk_desc *blk_get_dev(const char *ifname, int dev) { return NULL; } static inline struct blk_desc *sata_get_dev(int dev) { return NULL; } -static inline struct blk_desc *scsi_get_dev(int dev) { return NULL; } static inline int mmc_select_hwpart(int dev_num, int hwpart) { return -1; } static inline struct blk_desc *systemace_get_dev(int dev) { return NULL; } static inline struct blk_desc *mg_disk_get_dev(int dev) { return NULL; } From 4e7189d4d8c2ab46c4c580ae300c14d1a9c20b11 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 1 May 2016 11:36:17 -0600 Subject: [PATCH 065/162] dm: sata: Drop the get_dev() function This function is implemented by the legacy block functions now. Drop it. We cannot yet make sata_dev_desc[] private to common/sata.c as it is used by the SATA drivers. This will require the SATA interface to be reworked. Signed-off-by: Simon Glass --- disk/part.c | 2 +- include/part.h | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/disk/part.c b/disk/part.c index 67cb6c0c0b..4fc774bb97 100644 --- a/disk/part.c +++ b/disk/part.c @@ -26,7 +26,7 @@ const struct block_drvr block_drvr[] = { { .name = "ide", }, #endif #if defined(CONFIG_CMD_SATA) - {.name = "sata", .get_dev = sata_get_dev, }, + {.name = "sata", }, #endif #if defined(CONFIG_SCSI) { .name = "scsi", }, diff --git a/include/part.h b/include/part.h index ecb049f9a8..74bb5d6f96 100644 --- a/include/part.h +++ b/include/part.h @@ -73,7 +73,6 @@ typedef struct disk_partition { * error occurred. */ struct blk_desc *blk_get_dev(const char *ifname, int dev); -struct blk_desc *sata_get_dev(int dev); /** * mmc_select_hwpart() - Select the MMC hardware partiion on an MMC device @@ -171,7 +170,6 @@ extern const struct block_drvr block_drvr[]; #else static inline struct blk_desc *blk_get_dev(const char *ifname, int dev) { return NULL; } -static inline struct blk_desc *sata_get_dev(int dev) { return NULL; } static inline int mmc_select_hwpart(int dev_num, int hwpart) { return -1; } static inline struct blk_desc *systemace_get_dev(int dev) { return NULL; } static inline struct blk_desc *mg_disk_get_dev(int dev) { return NULL; } From f6d000edbeaddfe8e5b5e3be9fd3f6c76fdff6d2 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 1 May 2016 11:36:18 -0600 Subject: [PATCH 066/162] dm: systemace: Drop the get_dev() function This function is implemented by the legacy block functions now. Drop it. Signed-off-by: Simon Glass --- disk/part.c | 2 +- drivers/block/systemace.c | 14 +++----------- include/part.h | 2 -- include/systemace.h | 7 ------- 4 files changed, 4 insertions(+), 21 deletions(-) diff --git a/disk/part.c b/disk/part.c index 4fc774bb97..28c870664d 100644 --- a/disk/part.c +++ b/disk/part.c @@ -41,7 +41,7 @@ const struct block_drvr block_drvr[] = { }, #endif #if defined(CONFIG_SYSTEMACE) - { .name = "ace", .get_dev = systemace_get_dev, }, + { .name = "ace", }, #endif #if defined(CONFIG_SANDBOX) { .name = "host", .get_dev = host_get_dev, }, diff --git a/drivers/block/systemace.c b/drivers/block/systemace.c index 0d8e26f8aa..4f14d5feee 100644 --- a/drivers/block/systemace.c +++ b/drivers/block/systemace.c @@ -104,8 +104,7 @@ static void release_cf_lock(void) ace_writew((val & 0xffff), 0x18); } -#ifdef CONFIG_PARTITIONS -struct blk_desc *systemace_get_dev(int dev) +static int systemace_get_dev(int dev, struct blk_desc **descp) { /* The first time through this, the systemace_dev object is not yet initialized. In that case, fill it in. */ @@ -127,14 +126,7 @@ struct blk_desc *systemace_get_dev(int dev) part_init(&systemace_dev); } - - return &systemace_dev; -} -#endif - -static int systemace_get_devp(int dev, struct blk_desc **descp) -{ - *descp = systemace_get_dev(dev); + *descp = &systemace_dev; return 0; } @@ -269,5 +261,5 @@ U_BOOT_LEGACY_BLK(systemace) = { .if_typename = "ace", .if_type = IF_TYPE_SYSTEMACE, .max_devs = 1, - .get_dev = systemace_get_devp, + .get_dev = systemace_get_dev, }; diff --git a/include/part.h b/include/part.h index 74bb5d6f96..3b59139f14 100644 --- a/include/part.h +++ b/include/part.h @@ -91,7 +91,6 @@ struct blk_desc *blk_get_dev(const char *ifname, int dev); * @return 0 if OK, other value for an error */ int mmc_select_hwpart(int dev_num, int hwpart); -struct blk_desc *systemace_get_dev(int dev); struct blk_desc *mg_disk_get_dev(int dev); struct blk_desc *host_get_dev(int dev); int host_get_dev_err(int dev, struct blk_desc **blk_devp); @@ -171,7 +170,6 @@ extern const struct block_drvr block_drvr[]; static inline struct blk_desc *blk_get_dev(const char *ifname, int dev) { return NULL; } static inline int mmc_select_hwpart(int dev_num, int hwpart) { return -1; } -static inline struct blk_desc *systemace_get_dev(int dev) { return NULL; } static inline struct blk_desc *mg_disk_get_dev(int dev) { return NULL; } static inline struct blk_desc *host_get_dev(int dev) { return NULL; } diff --git a/include/systemace.h b/include/systemace.h index 3b6ec7da4b..bccb2a2ddf 100644 --- a/include/systemace.h +++ b/include/systemace.h @@ -7,11 +7,4 @@ * SPDX-License-Identifier: GPL-2.0+ */ -#ifdef CONFIG_SYSTEMACE - -# include - -struct blk_desc *systemace_get_dev(int dev); - -#endif /* CONFIG_SYSTEMACE */ #endif /* __SYSTEMACE_H */ From ae9ffccdac12b21ad55401d8554b5d835c9c8f22 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 1 May 2016 11:36:19 -0600 Subject: [PATCH 067/162] dm: blk: Drop the systemace.h header This has nothing of consequence. Remove it and its only inclusion site. Signed-off-by: Simon Glass --- drivers/block/systemace.c | 1 - include/systemace.h | 10 ---------- 2 files changed, 11 deletions(-) delete mode 100644 include/systemace.h diff --git a/drivers/block/systemace.c b/drivers/block/systemace.c index 4f14d5feee..79e1263a87 100644 --- a/drivers/block/systemace.c +++ b/drivers/block/systemace.c @@ -27,7 +27,6 @@ #include #include -#include #include #include diff --git a/include/systemace.h b/include/systemace.h deleted file mode 100644 index bccb2a2ddf..0000000000 --- a/include/systemace.h +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef __SYSTEMACE_H -#define __SYSTEMACE_H -/* - * Copyright (c) 2004 Picture Elements, Inc. - * Stephen Williams (steve@picturel.com) - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#endif /* __SYSTEMACE_H */ From f1d86fd3b15c2af53964d948c72c9a0a63511927 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 1 May 2016 11:36:20 -0600 Subject: [PATCH 068/162] dm: sandbox: Drop the host_get_dev() function This function is implemented by the legacy block functions now. Drop it. Signed-off-by: Simon Glass --- disk/part.c | 2 +- drivers/block/sandbox.c | 10 ---------- include/part.h | 2 -- 3 files changed, 1 insertion(+), 13 deletions(-) diff --git a/disk/part.c b/disk/part.c index 28c870664d..e635d90864 100644 --- a/disk/part.c +++ b/disk/part.c @@ -44,7 +44,7 @@ const struct block_drvr block_drvr[] = { { .name = "ace", }, #endif #if defined(CONFIG_SANDBOX) - { .name = "host", .get_dev = host_get_dev, }, + { .name = "host", }, #endif { }, }; diff --git a/drivers/block/sandbox.c b/drivers/block/sandbox.c index 2b6a89333b..ac28f83472 100644 --- a/drivers/block/sandbox.c +++ b/drivers/block/sandbox.c @@ -217,16 +217,6 @@ int host_get_dev_err(int devnum, struct blk_desc **blk_devp) return 0; } -struct blk_desc *host_get_dev(int dev) -{ - struct blk_desc *blk_dev; - - if (host_get_dev_err(dev, &blk_dev)) - return NULL; - - return blk_dev; -} - #ifdef CONFIG_BLK static const struct blk_ops sandbox_host_blk_ops = { .read = host_block_read, diff --git a/include/part.h b/include/part.h index 3b59139f14..47f5bafd63 100644 --- a/include/part.h +++ b/include/part.h @@ -92,7 +92,6 @@ struct blk_desc *blk_get_dev(const char *ifname, int dev); */ int mmc_select_hwpart(int dev_num, int hwpart); struct blk_desc *mg_disk_get_dev(int dev); -struct blk_desc *host_get_dev(int dev); int host_get_dev_err(int dev, struct blk_desc **blk_devp); /* disk/part.c */ @@ -171,7 +170,6 @@ static inline struct blk_desc *blk_get_dev(const char *ifname, int dev) { return NULL; } static inline int mmc_select_hwpart(int dev_num, int hwpart) { return -1; } static inline struct blk_desc *mg_disk_get_dev(int dev) { return NULL; } -static inline struct blk_desc *host_get_dev(int dev) { return NULL; } static inline int part_get_info(struct blk_desc *dev_desc, int part, disk_partition_t *info) { return -1; } From 38bd29beaaf51f92d986ef63e5539f0bd0d371d8 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 1 May 2016 11:36:21 -0600 Subject: [PATCH 069/162] dm: part: Drop the get_dev() method This is now handled by the legacy block driver. The get_dev() method is no-longer used. Drop it. Signed-off-by: Simon Glass --- include/part.h | 1 - 1 file changed, 1 deletion(-) diff --git a/include/part.h b/include/part.h index 47f5bafd63..bc9dc64912 100644 --- a/include/part.h +++ b/include/part.h @@ -12,7 +12,6 @@ struct block_drvr { char *name; - struct blk_desc* (*get_dev)(int dev); int (*select_hwpart)(int dev_num, int hwpart); }; From 145df842b443a2f2323a11f6e61223e3767dc55c Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 1 May 2016 11:36:22 -0600 Subject: [PATCH 070/162] dm: ide: Add support for driver-model block devices Add driver-model block-device support to the IDE implementation. Signed-off-by: Simon Glass --- common/ide.c | 32 ++++++++++++++++++++++++++++++++ include/ide.h | 8 ++++++++ 2 files changed, 40 insertions(+) diff --git a/common/ide.c b/common/ide.c index 5dc90d45ec..ac5b91c01a 100644 --- a/common/ide.c +++ b/common/ide.c @@ -7,6 +7,7 @@ #include #include +#include #include #include #include @@ -873,8 +874,10 @@ void ide_init(void) ide_dev_desc[i].log2blksz = LOG2_INVALID(typeof(ide_dev_desc[i].log2blksz)); ide_dev_desc[i].lba = 0; +#ifndef CONFIG_BLK ide_dev_desc[i].block_read = ide_read; ide_dev_desc[i].block_write = ide_write; +#endif if (!ide_bus_ok[IDE_BUS(i)]) continue; ide_led(led, 1); /* LED on */ @@ -975,9 +978,17 @@ __weak void ide_input_data(int dev, ulong *sect_buf, int words) #endif /* CONFIG_IDE_SWAP_IO */ +#ifdef CONFIG_BLK +ulong ide_read(struct udevice *dev, lbaint_t blknr, lbaint_t blkcnt, + void *buffer) +#else ulong ide_read(struct blk_desc *block_dev, lbaint_t blknr, lbaint_t blkcnt, void *buffer) +#endif { +#ifdef CONFIG_BLK + struct blk_desc *block_dev = dev_get_uclass_platdata(dev); +#endif int device = block_dev->devnum; ulong n = 0; unsigned char c; @@ -1097,9 +1108,17 @@ IDE_READ_E: return n; } +#ifdef CONFIG_BLK +ulong ide_write(struct udevice *dev, lbaint_t blknr, lbaint_t blkcnt, + const void *buffer) +#else ulong ide_write(struct blk_desc *block_dev, lbaint_t blknr, lbaint_t blkcnt, const void *buffer) +#endif { +#ifdef CONFIG_BLK + struct blk_desc *block_dev = dev_get_uclass_platdata(dev); +#endif int device = block_dev->devnum; ulong n = 0; unsigned char c; @@ -1191,9 +1210,22 @@ int ide_device_present(int dev) } #endif +#ifdef CONFIG_BLK +static const struct blk_ops ide_blk_ops = { + .read = ide_read, + .write = ide_write, +}; + +U_BOOT_DRIVER(ide_blk) = { + .name = "ide_blk", + .id = UCLASS_BLK, + .ops = &ide_blk_ops, +}; +#else U_BOOT_LEGACY_BLK(ide) = { .if_typename = "ide", .if_type = IF_TYPE_IDE, .max_devs = CONFIG_SYS_IDE_MAXDEVICE, .desc = ide_dev_desc, }; +#endif diff --git a/include/ide.h b/include/ide.h index a4e65cf2a9..9b0a4a96fa 100644 --- a/include/ide.h +++ b/include/ide.h @@ -34,10 +34,18 @@ void ide_led(uchar led, uchar status); void ide_init(void); struct blk_desc; +struct udevice; +#ifdef CONFIG_BLK +ulong ide_read(struct udevice *dev, lbaint_t blknr, lbaint_t blkcnt, + void *buffer); +ulong ide_write(struct udevice *dev, lbaint_t blknr, lbaint_t blkcnt, + const void *buffer); +#else ulong ide_read(struct blk_desc *block_dev, lbaint_t blknr, lbaint_t blkcnt, void *buffer); ulong ide_write(struct blk_desc *block_dev, lbaint_t blknr, lbaint_t blkcnt, const void *buffer); +#endif #ifdef CONFIG_IDE_PREINIT int ide_preinit(void); From 74c6dc14447e8386dd0799611d316eae5aad1e10 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 1 May 2016 11:36:23 -0600 Subject: [PATCH 071/162] dm: sandbox: Enable IDE Enable building the IDE code for sandbox. This is for build coverage only. It does not currently work. Signed-off-by: Simon Glass --- include/configs/sandbox.h | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/include/configs/sandbox.h b/include/configs/sandbox.h index 9790a14b02..a2926fd733 100644 --- a/include/configs/sandbox.h +++ b/include/configs/sandbox.h @@ -192,4 +192,14 @@ #define CONFIG_CMD_LZMADEC #define CONFIG_CMD_DATE +#define CONFIG_CMD_IDE +#define CONFIG_SYS_IDE_MAXBUS 1 +#define CONFIG_SYS_ATA_IDE0_OFFSET 0 +#define CONFIG_SYS_IDE_MAXDEVICE 2 +#define CONFIG_SYS_ATA_BASE_ADDR 0x100 +#define CONFIG_SYS_ATA_DATA_OFFSET 0 +#define CONFIG_SYS_ATA_REG_OFFSET 1 +#define CONFIG_SYS_ATA_ALT_OFFSET 2 +#define CONFIG_SYS_ATA_STRIDE 4 + #endif From 535556b2aa64966970ff75a8307549506a1a168a Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 1 May 2016 11:36:24 -0600 Subject: [PATCH 072/162] dm: scsi: Add support for driver-model block devices Add driver-model block-device support to the SCSI implementation. Signed-off-by: Simon Glass --- common/scsi.c | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/common/scsi.c b/common/scsi.c index 5b6531f01b..8ac28dd416 100644 --- a/common/scsi.c +++ b/common/scsi.c @@ -6,6 +6,7 @@ */ #include +#include #include #include #include @@ -149,9 +150,17 @@ void scsi_setup_inquiry(ccb *pccb) pccb->msgout[0] = SCSI_IDENTIFY; /* NOT USED */ } +#ifdef CONFIG_BLK +static ulong scsi_read(struct udevice *dev, lbaint_t blknr, lbaint_t blkcnt, + void *buffer) +#else static ulong scsi_read(struct blk_desc *block_dev, lbaint_t blknr, lbaint_t blkcnt, void *buffer) +#endif { +#ifdef CONFIG_BLK + struct blk_desc *block_dev = dev_get_uclass_platdata(dev); +#endif int device = block_dev->devnum; lbaint_t start, blks; uintptr_t buf_addr; @@ -216,9 +225,17 @@ static ulong scsi_read(struct blk_desc *block_dev, lbaint_t blknr, /* Almost the maximum amount of the scsi_ext command.. */ #define SCSI_MAX_WRITE_BLK 0xFFFF +#ifdef CONFIG_BLK +static ulong scsi_write(struct udevice *dev, lbaint_t blknr, lbaint_t blkcnt, + const void *buffer) +#else static ulong scsi_write(struct blk_desc *block_dev, lbaint_t blknr, lbaint_t blkcnt, const void *buffer) +#endif { +#ifdef CONFIG_BLK + struct blk_desc *block_dev = dev_get_uclass_platdata(dev); +#endif int device = block_dev->devnum; lbaint_t start, blks; uintptr_t buf_addr; @@ -469,8 +486,10 @@ void scsi_scan(int mode) scsi_dev_desc[i].if_type = IF_TYPE_SCSI; scsi_dev_desc[i].devnum = i; scsi_dev_desc[i].part_type = PART_TYPE_UNKNOWN; +#ifndef CONFIG_BLK scsi_dev_desc[i].block_read = scsi_read; scsi_dev_desc[i].block_write = scsi_write; +#endif } scsi_max_devs = 0; for (i = 0; i < CONFIG_SYS_SCSI_MAX_SCSI_ID; i++) { @@ -552,9 +571,22 @@ removable: #endif } +#ifdef CONFIG_BLK +static const struct blk_ops scsi_blk_ops = { + .read = scsi_read, + .write = scsi_write, +}; + +U_BOOT_DRIVER(scsi_blk) = { + .name = "scsi_blk", + .id = UCLASS_BLK, + .ops = &scsi_blk_ops, +}; +#else U_BOOT_LEGACY_BLK(scsi) = { .if_typename = "sata", .if_type = IF_TYPE_SCSI, .max_devs = CONFIG_SYS_SCSI_MAX_DEVICE, .desc = scsi_dev_desc, }; +#endif From e8c0a2509c6ec62a5c58a39c338cc1127bc83e1a Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 1 May 2016 11:36:25 -0600 Subject: [PATCH 073/162] dm: sandbox: Enable SCSI Enable building the SCSI code for sandbox. This increases build coverage for sandbox. Signed-off-by: Simon Glass --- include/configs/sandbox.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/include/configs/sandbox.h b/include/configs/sandbox.h index a2926fd733..affc9cc390 100644 --- a/include/configs/sandbox.h +++ b/include/configs/sandbox.h @@ -202,4 +202,10 @@ #define CONFIG_SYS_ATA_ALT_OFFSET 2 #define CONFIG_SYS_ATA_STRIDE 4 +#define CONFIG_SCSI +#define CONFIG_SCSI_AHCI_PLAT +#define CONFIG_SYS_SCSI_MAX_DEVICE 2 +#define CONFIG_SYS_SCSI_MAX_SCSI_ID 8 +#define CONFIG_SYS_SCSI_MAX_LUN 4 + #endif From f5a14af9c42be077404dbbeaebbb629f7ddcbed6 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 1 May 2016 11:36:26 -0600 Subject: [PATCH 074/162] dm: sata: Add support for driver-model block devices Add driver-model block-device support to the SATA implementation. This is just a dummy implementation for now, since the SATA low-level API uses numbered devices and that doesn't fit with driver model. Signed-off-by: Simon Glass --- common/sata.c | 31 ++++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/common/sata.c b/common/sata.c index 1d52fcb2dc..88f08c95ec 100644 --- a/common/sata.c +++ b/common/sata.c @@ -11,6 +11,7 @@ */ #include +#include #include struct blk_desc sata_dev_desc[CONFIG_SYS_SATA_MAX_DEVICE]; @@ -22,6 +23,19 @@ struct blk_desc *sata_get_dev(int dev) } #endif +#ifdef CONFIG_BLK +static unsigned long sata_bread(struct udevice *dev, lbaint_t start, + lbaint_t blkcnt, void *dst) +{ + return -ENOSYS; +} + +static unsigned long sata_bwrite(struct udevice *dev, lbaint_t start, + lbaint_t blkcnt, const void *buffer) +{ + return -ENOSYS; +} +#else static unsigned long sata_bread(struct blk_desc *block_dev, lbaint_t start, lbaint_t blkcnt, void *dst) { @@ -33,6 +47,7 @@ static unsigned long sata_bwrite(struct blk_desc *block_dev, lbaint_t start, { return sata_write(block_dev->devnum, start, blkcnt, buffer); } +#endif int __sata_initialize(void) { @@ -48,9 +63,10 @@ int __sata_initialize(void) sata_dev_desc[i].lba = 0; sata_dev_desc[i].blksz = 512; sata_dev_desc[i].log2blksz = LOG2(sata_dev_desc[i].blksz); +#ifndef CONFIG_BLK sata_dev_desc[i].block_read = sata_bread; sata_dev_desc[i].block_write = sata_bwrite; - +#endif rc = init_sata(i); if (!rc) { rc = scan_sata(i); @@ -78,9 +94,22 @@ __weak int __sata_stop(void) } int sata_stop(void) __attribute__((weak, alias("__sata_stop"))); +#ifdef CONFIG_BLK +static const struct blk_ops sata_blk_ops = { + .read = sata_bread, + .write = sata_bwrite, +}; + +U_BOOT_DRIVER(sata_blk) = { + .name = "sata_blk", + .id = UCLASS_BLK, + .ops = &sata_blk_ops, +}; +#else U_BOOT_LEGACY_BLK(sata) = { .if_typename = "sata", .if_type = IF_TYPE_SATA, .max_devs = CONFIG_SYS_SATA_MAX_DEVICE, .desc = sata_dev_desc, }; +#endif From 199a1201ab901413a80c64a9eee72f82977ba8d3 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 1 May 2016 11:36:27 -0600 Subject: [PATCH 075/162] dm: sandbox: Enable SATA Enable building the SATA code for sandbox. This increases build coverage for sandbox. Signed-off-by: Simon Glass --- include/configs/sandbox.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/include/configs/sandbox.h b/include/configs/sandbox.h index affc9cc390..71276119e4 100644 --- a/include/configs/sandbox.h +++ b/include/configs/sandbox.h @@ -208,4 +208,7 @@ #define CONFIG_SYS_SCSI_MAX_SCSI_ID 8 #define CONFIG_SYS_SCSI_MAX_LUN 4 +#define CONFIG_CMD_SATA +#define CONFIG_SYS_SATA_MAX_DEVICE 2 + #endif From 52138fd4072b64448855eac4c2c9815b46f5b43c Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 1 May 2016 11:36:28 -0600 Subject: [PATCH 076/162] dm: blk: Allow blk_create_device() to allocate the device number Allow a devnum parameter of -1 to indicate that the device number should be alocated automatically. The next highest available device number for that interface type is used. Signed-off-by: Simon Glass --- drivers/block/blk-uclass.c | 29 +++++++++++++++++++++++++++++ include/blk.h | 15 ++++++++++++++- 2 files changed, 43 insertions(+), 1 deletion(-) diff --git a/drivers/block/blk-uclass.c b/drivers/block/blk-uclass.c index 3687b9a100..c947d95023 100644 --- a/drivers/block/blk-uclass.c +++ b/drivers/block/blk-uclass.c @@ -411,6 +411,26 @@ int blk_prepare_device(struct udevice *dev) return 0; } +int blk_find_max_devnum(enum if_type if_type) +{ + struct udevice *dev; + int max_devnum = -ENODEV; + struct uclass *uc; + int ret; + + ret = uclass_get(UCLASS_BLK, &uc); + if (ret) + return ret; + uclass_foreach_dev(dev, uc) { + struct blk_desc *desc = dev_get_uclass_platdata(dev); + + if (desc->if_type == if_type && desc->devnum > max_devnum) + max_devnum = desc->devnum; + } + + return max_devnum; +} + int blk_create_device(struct udevice *parent, const char *drv_name, const char *name, int if_type, int devnum, int blksz, lbaint_t size, struct udevice **devp) @@ -428,6 +448,15 @@ int blk_create_device(struct udevice *parent, const char *drv_name, desc->lba = size / blksz; desc->part_type = PART_TYPE_UNKNOWN; desc->bdev = dev; + if (devnum == -1) { + ret = blk_find_max_devnum(if_type); + if (ret == -ENODEV) + devnum = 0; + else if (ret < 0) + return ret; + else + devnum = ret + 1; + } desc->devnum = devnum; *devp = dev; diff --git a/include/blk.h b/include/blk.h index 2caac9c96b..547c3b48dc 100644 --- a/include/blk.h +++ b/include/blk.h @@ -270,7 +270,8 @@ int blk_next_device(struct udevice **devp); * @drv_name: Driver name to use for the block device * @name: Name for the device * @if_type: Interface type (enum if_type_t) - * @devnum: Device number, specific to the interface type + * @devnum: Device number, specific to the interface type, or -1 to + * allocate the next available number * @blksz: Block size of the device in bytes (typically 512) * @size: Total size of the device in bytes * @devp: the new device (which has not been probed) @@ -299,6 +300,18 @@ int blk_prepare_device(struct udevice *dev); */ int blk_unbind_all(int if_type); +/** + * blk_find_max_devnum() - find the maximum device number for an interface type + * + * Finds the last allocated device number for an interface type @if_type. The + * next number is safe to use for a newly allocated device. + * + * @if_type: Interface type to scan + * @return maximum device number found, or -ENODEV if none, or other -ve on + * error + */ +int blk_find_max_devnum(enum if_type if_type); + #else #include /* From 9107c973d32c72a6f7ac909fc4a6884a42e4e607 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 1 May 2016 11:36:29 -0600 Subject: [PATCH 077/162] dm: blk: Add a easier way to create a named block device Add a function that automatically builds the device name given the parent and a supplied string. Most callers will want to do this, so putting this functionality in one place makes more sense. Signed-off-by: Simon Glass --- common/usb_storage.c | 13 +++++-------- drivers/block/blk-uclass.c | 15 +++++++++++++++ include/blk.h | 17 +++++++++++++++++ 3 files changed, 37 insertions(+), 8 deletions(-) diff --git a/common/usb_storage.c b/common/usb_storage.c index f2da3a3cad..7e6e52d2ec 100644 --- a/common/usb_storage.c +++ b/common/usb_storage.c @@ -200,7 +200,6 @@ static int usb_stor_probe_device(struct usb_device *udev) #ifdef CONFIG_BLK struct us_data *data; - char dev_name[30], *str; int ret; #else int start; @@ -223,14 +222,12 @@ static int usb_stor_probe_device(struct usb_device *udev) for (lun = 0; lun <= max_lun; lun++) { struct blk_desc *blkdev; struct udevice *dev; + char str[10]; - snprintf(dev_name, sizeof(dev_name), "%s.lun%d", - udev->dev->name, lun); - str = strdup(dev_name); - if (!str) - return -ENOMEM; - ret = blk_create_device(udev->dev, "usb_storage_blk", str, - IF_TYPE_USB, usb_max_devs, 512, 0, &dev); + snprintf(str, sizeof(str), "lun%d", lun); + ret = blk_create_devicef(udev->dev, "usb_storage_blk", str, + IF_TYPE_USB, usb_max_devs, 512, 0, + &dev); if (ret) { debug("Cannot bind driver\n"); return ret; diff --git a/drivers/block/blk-uclass.c b/drivers/block/blk-uclass.c index c947d95023..6ecbff0e93 100644 --- a/drivers/block/blk-uclass.c +++ b/drivers/block/blk-uclass.c @@ -463,6 +463,21 @@ int blk_create_device(struct udevice *parent, const char *drv_name, return 0; } +int blk_create_devicef(struct udevice *parent, const char *drv_name, + const char *name, int if_type, int devnum, int blksz, + lbaint_t size, struct udevice **devp) +{ + char dev_name[30], *str; + + snprintf(dev_name, sizeof(dev_name), "%s.%s", parent->name, name); + str = strdup(dev_name); + if (!str) + return -ENOMEM; + + return blk_create_device(parent, drv_name, str, if_type, devnum, + blksz, size, devp); +} + int blk_unbind_all(int if_type) { struct uclass *uc; diff --git a/include/blk.h b/include/blk.h index 547c3b48dc..82b2c1a706 100644 --- a/include/blk.h +++ b/include/blk.h @@ -280,6 +280,23 @@ int blk_create_device(struct udevice *parent, const char *drv_name, const char *name, int if_type, int devnum, int blksz, lbaint_t size, struct udevice **devp); +/** + * blk_create_devicef() - Create a new named block device + * + * @parent: Parent of the new device + * @drv_name: Driver name to use for the block device + * @name: Name for the device (parent name is prepended) + * @if_type: Interface type (enum if_type_t) + * @devnum: Device number, specific to the interface type, or -1 to + * allocate the next available number + * @blksz: Block size of the device in bytes (typically 512) + * @size: Total size of the device in bytes + * @devp: the new device (which has not been probed) + */ +int blk_create_devicef(struct udevice *parent, const char *drv_name, + const char *name, int if_type, int devnum, int blksz, + lbaint_t size, struct udevice **devp); + /** * blk_prepare_device() - Prepare a block device for use * From a0ff24c4672654fa6d13498e3a3367935bdc7334 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 1 May 2016 11:36:30 -0600 Subject: [PATCH 078/162] dm: systemace: Reorder function to avoid forward declarataions Move the systemace_get_dev() function below systemace_read() so that we can avoid a forward declaration. Signed-off-by: Simon Glass --- drivers/block/systemace.c | 57 ++++++++++++++++++--------------------- 1 file changed, 26 insertions(+), 31 deletions(-) diff --git a/drivers/block/systemace.c b/drivers/block/systemace.c index 79e1263a87..eeba7f0890 100644 --- a/drivers/block/systemace.c +++ b/drivers/block/systemace.c @@ -68,10 +68,6 @@ static u16 ace_readw(unsigned off) return in16(base + off); } -static unsigned long systemace_read(struct blk_desc *block_dev, - unsigned long start, lbaint_t blkcnt, - void *buffer); - static struct blk_desc systemace_dev = { 0 }; static int get_cf_lock(void) @@ -103,33 +99,6 @@ static void release_cf_lock(void) ace_writew((val & 0xffff), 0x18); } -static int systemace_get_dev(int dev, struct blk_desc **descp) -{ - /* The first time through this, the systemace_dev object is - not yet initialized. In that case, fill it in. */ - if (systemace_dev.blksz == 0) { - systemace_dev.if_type = IF_TYPE_UNKNOWN; - systemace_dev.devnum = 0; - systemace_dev.part_type = PART_TYPE_UNKNOWN; - systemace_dev.type = DEV_TYPE_HARDDISK; - systemace_dev.blksz = 512; - systemace_dev.log2blksz = LOG2(systemace_dev.blksz); - systemace_dev.removable = 1; - systemace_dev.block_read = systemace_read; - - /* - * Ensure the correct bus mode (8/16 bits) gets enabled - */ - ace_writew(width == 8 ? 0 : 0x0001, 0); - - part_init(&systemace_dev); - - } - *descp = &systemace_dev; - - return 0; -} - /* * This function is called (by dereferencing the block_read pointer in * the dev_desc) to read blocks of data. The return value is the @@ -256,6 +225,32 @@ static unsigned long systemace_read(struct blk_desc *block_dev, return blkcnt; } +static int systemace_get_dev(int dev, struct blk_desc **descp) +{ + /* The first time through this, the systemace_dev object is + not yet initialized. In that case, fill it in. */ + if (systemace_dev.blksz == 0) { + systemace_dev.if_type = IF_TYPE_UNKNOWN; + systemace_dev.devnum = 0; + systemace_dev.part_type = PART_TYPE_UNKNOWN; + systemace_dev.type = DEV_TYPE_HARDDISK; + systemace_dev.blksz = 512; + systemace_dev.log2blksz = LOG2(systemace_dev.blksz); + systemace_dev.removable = 1; + systemace_dev.block_read = systemace_read; + + /* + * Ensure the correct bus mode (8/16 bits) gets enabled + */ + ace_writew(width == 8 ? 0 : 0x0001, 0); + + part_init(&systemace_dev); + } + *descp = &systemace_dev; + + return 0; +} + U_BOOT_LEGACY_BLK(systemace) = { .if_typename = "ace", .if_type = IF_TYPE_SYSTEMACE, From 4560ee470f021cfc3f6be37890c1391731c26f38 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 1 May 2016 11:36:31 -0600 Subject: [PATCH 079/162] dm: systemace: Add driver-mode block-device support Add support for CONFIG_BLK to the systemace driver. Signed-off-by: Simon Glass --- drivers/block/systemace.c | 44 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/drivers/block/systemace.c b/drivers/block/systemace.c index eeba7f0890..9392beaf05 100644 --- a/drivers/block/systemace.c +++ b/drivers/block/systemace.c @@ -27,6 +27,7 @@ #include #include +#include #include #include @@ -68,7 +69,9 @@ static u16 ace_readw(unsigned off) return in16(base + off); } +#ifndef CONFIG_BLK static struct blk_desc systemace_dev = { 0 }; +#endif static int get_cf_lock(void) { @@ -104,9 +107,14 @@ static void release_cf_lock(void) * the dev_desc) to read blocks of data. The return value is the * number of blocks read. A zero return indicates an error. */ +#ifdef CONFIG_BLK +static unsigned long systemace_read(struct udevice *dev, unsigned long start, + lbaint_t blkcnt, void *buffer) +#else static unsigned long systemace_read(struct blk_desc *block_dev, unsigned long start, lbaint_t blkcnt, void *buffer) +#endif { int retry; unsigned blk_countdown; @@ -225,6 +233,41 @@ static unsigned long systemace_read(struct blk_desc *block_dev, return blkcnt; } +#ifdef CONFIG_BLK +static int systemace_bind(struct udevice *dev) +{ + struct blk_desc *bdesc; + struct udevice *bdev; + int ret; + + ret = blk_create_devicef(dev, "systemace_blk", "blk", IF_TYPE_SYSTEMACE, + -1, 512, 0, &bdev); + if (ret) { + debug("Cannot create block device\n"); + return ret; + } + bdesc = dev_get_uclass_platdata(bdev); + bdesc->removable = 1; + bdesc->part_type = PART_TYPE_UNKNOWN; + bdesc->log2blksz = LOG2(bdesc->blksz); + + /* Ensure the correct bus mode (8/16 bits) gets enabled */ + ace_writew(width == 8 ? 0 : 0x0001, 0); + + return 0; +} + +static const struct blk_ops systemace_blk_ops = { + .read = systemace_read, +}; + +U_BOOT_DRIVER(systemace_blk) = { + .name = "systemace_blk", + .id = UCLASS_BLK, + .ops = &systemace_blk_ops, + .bind = systemace_bind, +}; +#else static int systemace_get_dev(int dev, struct blk_desc **descp) { /* The first time through this, the systemace_dev object is @@ -257,3 +300,4 @@ U_BOOT_LEGACY_BLK(systemace) = { .max_devs = 1, .get_dev = systemace_get_dev, }; +#endif From cd995a8aa0127128132bb50f485c53bfb9593312 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 1 May 2016 11:36:32 -0600 Subject: [PATCH 080/162] dm: sandbox: Enable systemace Enable building the systemace code for sandbox. This increases build coverage for sandbox. Signed-off-by: Simon Glass --- include/configs/sandbox.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/include/configs/sandbox.h b/include/configs/sandbox.h index 71276119e4..c51d4cd737 100644 --- a/include/configs/sandbox.h +++ b/include/configs/sandbox.h @@ -211,4 +211,8 @@ #define CONFIG_CMD_SATA #define CONFIG_SYS_SATA_MAX_DEVICE 2 +#define CONFIG_SYSTEMACE +#define CONFIG_SYS_SYSTEMACE_WIDTH 16 +#define CONFIG_SYS_SYSTEMACE_BASE 0 + #endif From 72a85c0d2dfe965c831670f06d3803aaad7bb5b1 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 1 May 2016 13:52:22 -0600 Subject: [PATCH 081/162] dm: blk: Fix allocation of block-device numbering Due to code ordering the block devices are not numbered sequentially. Fix this. Signed-off-by: Simon Glass --- drivers/block/blk-uclass.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/block/blk-uclass.c b/drivers/block/blk-uclass.c index 6ecbff0e93..f67f9b9d55 100644 --- a/drivers/block/blk-uclass.c +++ b/drivers/block/blk-uclass.c @@ -439,15 +439,6 @@ int blk_create_device(struct udevice *parent, const char *drv_name, struct udevice *dev; int ret; - ret = device_bind_driver(parent, drv_name, name, &dev); - if (ret) - return ret; - desc = dev_get_uclass_platdata(dev); - desc->if_type = if_type; - desc->blksz = blksz; - desc->lba = size / blksz; - desc->part_type = PART_TYPE_UNKNOWN; - desc->bdev = dev; if (devnum == -1) { ret = blk_find_max_devnum(if_type); if (ret == -ENODEV) @@ -457,6 +448,15 @@ int blk_create_device(struct udevice *parent, const char *drv_name, else devnum = ret + 1; } + ret = device_bind_driver(parent, drv_name, name, &dev); + if (ret) + return ret; + desc = dev_get_uclass_platdata(dev); + desc->if_type = if_type; + desc->blksz = blksz; + desc->lba = size / blksz; + desc->part_type = PART_TYPE_UNKNOWN; + desc->bdev = dev; desc->devnum = devnum; *devp = dev; From a2040facd23b88082b9b40f0aa9bcfd495eab88e Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 1 May 2016 13:52:23 -0600 Subject: [PATCH 082/162] dm: core: Allow device names to be freed automatically Some devices have a name that is stored in allocated memory. At present there is no mechanism to free this memory when the device is unbound. Add a device flag to track whether a name is allocated and a function to add the flag. Free the memory when the device is unbound. Signed-off-by: Simon Glass --- drivers/core/device-remove.c | 2 ++ drivers/core/device.c | 6 ++++++ include/dm/device.h | 16 ++++++++++++++++ 3 files changed, 24 insertions(+) diff --git a/drivers/core/device-remove.c b/drivers/core/device-remove.c index e1714b2202..0e56b23fbb 100644 --- a/drivers/core/device-remove.c +++ b/drivers/core/device-remove.c @@ -112,6 +112,8 @@ int device_unbind(struct udevice *dev) devres_release_all(dev); + if (dev->flags & DM_NAME_ALLOCED) + free((char *)dev->name); free(dev); return 0; diff --git a/drivers/core/device.c b/drivers/core/device.c index 2b12ce7835..5c2dc7021f 100644 --- a/drivers/core/device.c +++ b/drivers/core/device.c @@ -706,12 +706,18 @@ bool device_is_last_sibling(struct udevice *dev) return list_is_last(&dev->sibling_node, &parent->child_head); } +void device_set_name_alloced(struct udevice *dev) +{ + dev->flags |= DM_NAME_ALLOCED; +} + int device_set_name(struct udevice *dev, const char *name) { name = strdup(name); if (!name) return -ENOMEM; dev->name = name; + device_set_name_alloced(dev); return 0; } diff --git a/include/dm/device.h b/include/dm/device.h index 8970fc015c..e9a8ec72c9 100644 --- a/include/dm/device.h +++ b/include/dm/device.h @@ -41,6 +41,9 @@ struct driver_info; /* Device is bound */ #define DM_FLAG_BOUND (1 << 6) +/* Device name is allocated and should be freed on unbind() */ +#define DM_NAME_ALLOCED (1 << 7) + /** * struct udevice - An instance of a driver * @@ -523,6 +526,9 @@ bool device_is_last_sibling(struct udevice *dev); * this is unnecessary but for probed devices which don't get a useful name * this function can be helpful. * + * The name is allocated and will be freed automatically when the device is + * unbound. + * * @dev: Device to update * @name: New name (this string is allocated new memory and attached to * the device) @@ -531,6 +537,16 @@ bool device_is_last_sibling(struct udevice *dev); */ int device_set_name(struct udevice *dev, const char *name); +/** + * device_set_name_alloced() - note that a device name is allocated + * + * This sets the DM_NAME_ALLOCED flag for the device, so that when it is + * unbound the name will be freed. This avoids memory leaks. + * + * @dev: Device to update + */ +void device_set_name_alloced(struct udevice *dev); + /** * device_is_on_pci_bus - Test if a device is on a PCI bus * From d0773524e18d2439390c88611b49f23ca46a82be Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 1 May 2016 13:52:24 -0600 Subject: [PATCH 083/162] dm: blk: Free the block device name when unbound Mark the device name as allocated so that it will be freed correctly when the device is unbound. Signed-off-by: Simon Glass --- drivers/block/blk-uclass.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/drivers/block/blk-uclass.c b/drivers/block/blk-uclass.c index f67f9b9d55..a37239ee50 100644 --- a/drivers/block/blk-uclass.c +++ b/drivers/block/blk-uclass.c @@ -468,14 +468,22 @@ int blk_create_devicef(struct udevice *parent, const char *drv_name, lbaint_t size, struct udevice **devp) { char dev_name[30], *str; + int ret; snprintf(dev_name, sizeof(dev_name), "%s.%s", parent->name, name); str = strdup(dev_name); if (!str) return -ENOMEM; - return blk_create_device(parent, drv_name, str, if_type, devnum, - blksz, size, devp); + ret = blk_create_device(parent, drv_name, str, if_type, devnum, + blksz, size, devp); + if (ret) { + free(str); + return ret; + } + device_set_name_alloced(*devp); + + return ret; } int blk_unbind_all(int if_type) From ff3882ac23fcfda81284f372924063036bea507b Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 1 May 2016 13:52:25 -0600 Subject: [PATCH 084/162] dm: mmc: Move mmc_switch_part() above its callers This function is defined after it is used. In preparation for making it static, move it up a little. Also drop the printf() which should not appear in a driver. Signed-off-by: Simon Glass --- drivers/mmc/mmc.c | 45 +++++++++++++++++++++------------------------ 1 file changed, 21 insertions(+), 24 deletions(-) diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c index 185d7b2a8e..2211ac6d99 100644 --- a/drivers/mmc/mmc.c +++ b/drivers/mmc/mmc.c @@ -582,30 +582,6 @@ static int mmc_set_capacity(struct mmc *mmc, int part_num) return 0; } -int mmc_select_hwpart(int dev_num, int hwpart) -{ - struct mmc *mmc = find_mmc_device(dev_num); - int ret; - - if (!mmc) - return -ENODEV; - - if (mmc->block_dev.hwpart == hwpart) - return 0; - - if (mmc->part_config == MMCPART_NOAVAILABLE) { - printf("Card doesn't support part_switch\n"); - return -EMEDIUMTYPE; - } - - ret = mmc_switch_part(dev_num, hwpart); - if (ret) - return ret; - - return 0; -} - - int mmc_switch_part(int dev_num, unsigned int part_num) { struct mmc *mmc = find_mmc_device(dev_num); @@ -630,6 +606,27 @@ int mmc_switch_part(int dev_num, unsigned int part_num) return ret; } +int mmc_select_hwpart(int dev_num, int hwpart) +{ + struct mmc *mmc = find_mmc_device(dev_num); + int ret; + + if (!mmc) + return -ENODEV; + + if (mmc->block_dev.hwpart == hwpart) + return 0; + + if (mmc->part_config == MMCPART_NOAVAILABLE) + return -EMEDIUMTYPE; + + ret = mmc_switch_part(dev_num, hwpart); + if (ret) + return ret; + + return 0; +} + int mmc_hwpart_config(struct mmc *mmc, const struct mmc_hwpart_conf *conf, enum mmc_hwpart_conf_mode mode) From e17d1143c1a3f6f9bb1b21acb50e5e6a79855023 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 1 May 2016 13:52:26 -0600 Subject: [PATCH 085/162] dm: mmc: Implement the select_hwpart() method Implement this method so that hardware partitions will work correctly with MMC. Signed-off-by: Simon Glass --- drivers/mmc/mmc.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c index 2211ac6d99..e270f5f644 100644 --- a/drivers/mmc/mmc.c +++ b/drivers/mmc/mmc.c @@ -606,6 +606,27 @@ int mmc_switch_part(int dev_num, unsigned int part_num) return ret; } +static int mmc_select_hwpartp(struct blk_desc *desc, int hwpart) +{ + struct mmc *mmc = find_mmc_device(desc->devnum); + int ret; + + if (!mmc) + return -ENODEV; + + if (mmc->block_dev.hwpart == hwpart) + return 0; + + if (mmc->part_config == MMCPART_NOAVAILABLE) + return -EMEDIUMTYPE; + + ret = mmc_switch_part(desc->devnum, hwpart); + if (ret) + return ret; + + return 0; +} + int mmc_select_hwpart(int dev_num, int hwpart) { struct mmc *mmc = find_mmc_device(dev_num); @@ -1973,4 +1994,5 @@ U_BOOT_LEGACY_BLK(mmc) = { .if_type = IF_TYPE_MMC, .max_devs = -1, .get_dev = mmc_get_dev, + .select_hwpart = mmc_select_hwpartp, }; From cb5ec33d9096f1f57c5ccc97d44ca0fb771729f5 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 1 May 2016 13:52:27 -0600 Subject: [PATCH 086/162] dm: mmc: Add a function to obtain the block device The MMC block device is contained within struct mmc. But with driver model this will not be the case. Add a function to obtain the block device. We can later implement this for CONFIG_BLK. Signed-off-by: Simon Glass --- drivers/mmc/mmc.c | 5 +++++ include/mmc.h | 8 ++++++++ 2 files changed, 13 insertions(+) diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c index e270f5f644..49996a891c 100644 --- a/drivers/mmc/mmc.c +++ b/drivers/mmc/mmc.c @@ -24,6 +24,11 @@ static struct list_head mmc_devices; static int cur_dev_num = -1; +struct blk_desc *mmc_get_blk_desc(struct mmc *mmc) +{ + return &mmc->block_dev; +} + __weak int board_mmc_getwp(struct mmc *mmc) { return -1; diff --git a/include/mmc.h b/include/mmc.h index cdb56e7ac1..36449c34ea 100644 --- a/include/mmc.h +++ b/include/mmc.h @@ -498,4 +498,12 @@ int pci_mmc_init(const char *name, struct pci_device_id *mmc_supported); #define CONFIG_SYS_MMC_MAX_BLK_COUNT 65535 #endif +/** + * mmc_get_blk_desc() - Get the block descriptor for an MMC device + * + * @mmc: MMC device + * @return block device if found, else NULL + */ +struct blk_desc *mmc_get_blk_desc(struct mmc *mmc); + #endif /* _MMC_H_ */ From 0776167ec5541a2b4fa099dfea5a1aad2d4b7c72 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 1 May 2016 13:52:28 -0600 Subject: [PATCH 087/162] dm: mmc: spl: Use the legacy block interface in SPL Bring this in for SPL so that we can use generic code for loading from block devices. Signed-off-by: Simon Glass --- drivers/Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/Makefile b/drivers/Makefile index 696b3ac51b..99dd07fc76 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -37,6 +37,7 @@ obj-$(CONFIG_SPL_USB_HOST_SUPPORT) += usb/host/ obj-$(CONFIG_OMAP_USB_PHY) += usb/phy/ obj-$(CONFIG_SPL_SATA_SUPPORT) += block/ obj-$(CONFIG_SPL_USB_HOST_SUPPORT) += block/ +obj-$(CONFIG_SPL_MMC_SUPPORT) += block/ else From 69f45cd53b8ad8bc3afef2cf2410baf58fe75a6f Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 1 May 2016 13:52:29 -0600 Subject: [PATCH 088/162] dm: mmc: Use the new select_hwpart() API Avoid calling directly into the MMC code - use the new API call instead. Signed-off-by: Simon Glass --- cmd/mmc.c | 8 +++++--- common/env_mmc.c | 6 +++--- common/spl/spl_mmc.c | 2 +- drivers/dfu/dfu_mmc.c | 13 +++++++++---- drivers/mmc/mmc.c | 2 +- drivers/mmc/mmc_write.c | 5 +++-- include/mmc.h | 1 - 7 files changed, 22 insertions(+), 15 deletions(-) diff --git a/cmd/mmc.c b/cmd/mmc.c index 4f251870ee..8695c19187 100644 --- a/cmd/mmc.c +++ b/cmd/mmc.c @@ -314,12 +314,14 @@ static int do_mmcrpmb(cmd_tbl_t *cmdtp, int flag, } /* Switch to the RPMB partition */ original_part = mmc->block_dev.hwpart; - if (mmc_select_hwpart(curr_device, MMC_PART_RPMB) != 0) + if (blk_select_hwpart_devnum(IF_TYPE_MMC, curr_device, MMC_PART_RPMB) != + 0) return CMD_RET_FAILURE; ret = cp->cmd(cmdtp, flag, argc, argv); /* Return to original partition */ - if (mmc_select_hwpart(curr_device, original_part) != 0) + if (blk_select_hwpart_devnum(IF_TYPE_MMC, curr_device, original_part) != + 0) return CMD_RET_FAILURE; return ret; } @@ -467,7 +469,7 @@ static int do_mmc_dev(cmd_tbl_t *cmdtp, int flag, if (!mmc) return CMD_RET_FAILURE; - ret = mmc_select_hwpart(dev, part); + ret = blk_select_hwpart_devnum(IF_TYPE_MMC, dev, part); printf("switch to partitions #%d, %s\n", part, (!ret) ? "OK" : "ERROR"); if (ret) diff --git a/common/env_mmc.c b/common/env_mmc.c index bdb452e58c..c7fef188cd 100644 --- a/common/env_mmc.c +++ b/common/env_mmc.c @@ -86,8 +86,8 @@ static int mmc_set_env_part(struct mmc *mmc) dev = 0; #endif - env_mmc_orig_hwpart = mmc->block_dev.hwpart; - ret = mmc_select_hwpart(dev, part); + env_mmc_orig_hwpart = mmc_get_blk_desc(mmc)->hwpart; + ret = blk_select_hwpart_devnum(IF_TYPE_MMC, dev, part); if (ret) puts("MMC partition switch failed\n"); @@ -119,7 +119,7 @@ static void fini_mmc_for_env(struct mmc *mmc) #ifdef CONFIG_SPL_BUILD dev = 0; #endif - mmc_select_hwpart(dev, env_mmc_orig_hwpart); + blk_select_hwpart_devnum(IF_TYPE_MMC, dev, env_mmc_orig_hwpart); #endif } diff --git a/common/spl/spl_mmc.c b/common/spl/spl_mmc.c index 8d588d13a3..cf527da9f2 100644 --- a/common/spl/spl_mmc.c +++ b/common/spl/spl_mmc.c @@ -296,7 +296,7 @@ int spl_mmc_load_image(u32 boot_device) if (part == 7) part = 0; - err = mmc_switch_part(0, part); + err = blk_dselect_hwpart(mmc_get_blk_desc(mmc), part); if (err) { #ifdef CONFIG_SPL_LIBCOMMON_SUPPORT puts("spl: mmc partition switch failed\n"); diff --git a/drivers/dfu/dfu_mmc.c b/drivers/dfu/dfu_mmc.c index faece8883a..78724e467b 100644 --- a/drivers/dfu/dfu_mmc.c +++ b/drivers/dfu/dfu_mmc.c @@ -50,8 +50,9 @@ static int mmc_block_op(enum dfu_op op, struct dfu_entity *dfu, if (dfu->data.mmc.hw_partition >= 0) { part_num_bkp = mmc->block_dev.hwpart; - ret = mmc_select_hwpart(dfu->data.mmc.dev_num, - dfu->data.mmc.hw_partition); + ret = blk_select_hwpart_devnum(IF_TYPE_MMC, + dfu->data.mmc.dev_num, + dfu->data.mmc.hw_partition); if (ret) return ret; } @@ -75,12 +76,16 @@ static int mmc_block_op(enum dfu_op op, struct dfu_entity *dfu, if (n != blk_count) { error("MMC operation failed"); if (dfu->data.mmc.hw_partition >= 0) - mmc_select_hwpart(dfu->data.mmc.dev_num, part_num_bkp); + blk_select_hwpart_devnum(IF_TYPE_MMC, + dfu->data.mmc.dev_num, + part_num_bkp); return -EIO; } if (dfu->data.mmc.hw_partition >= 0) { - ret = mmc_select_hwpart(dfu->data.mmc.dev_num, part_num_bkp); + ret = blk_select_hwpart_devnum(IF_TYPE_MMC, + dfu->data.mmc.dev_num, + part_num_bkp); if (ret) return ret; } diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c index 49996a891c..7322f33404 100644 --- a/drivers/mmc/mmc.c +++ b/drivers/mmc/mmc.c @@ -257,7 +257,7 @@ static ulong mmc_bread(struct blk_desc *block_dev, lbaint_t start, if (!mmc) return 0; - err = mmc_select_hwpart(dev_num, block_dev->hwpart); + err = blk_dselect_hwpart(block_dev, block_dev->hwpart); if (err < 0) return 0; diff --git a/drivers/mmc/mmc_write.c b/drivers/mmc/mmc_write.c index 7b186f8500..f4d42aaa76 100644 --- a/drivers/mmc/mmc_write.c +++ b/drivers/mmc/mmc_write.c @@ -78,7 +78,8 @@ unsigned long mmc_berase(struct blk_desc *block_dev, lbaint_t start, if (!mmc) return -1; - err = mmc_select_hwpart(dev_num, block_dev->hwpart); + err = blk_select_hwpart_devnum(IF_TYPE_MMC, dev_num, + block_dev->hwpart); if (err < 0) return -1; @@ -182,7 +183,7 @@ ulong mmc_bwrite(struct blk_desc *block_dev, lbaint_t start, lbaint_t blkcnt, if (!mmc) return 0; - err = mmc_select_hwpart(dev_num, block_dev->hwpart); + err = blk_select_hwpart_devnum(IF_TYPE_MMC, dev_num, block_dev->hwpart); if (err < 0) return 0; diff --git a/include/mmc.h b/include/mmc.h index 36449c34ea..f01674d9fc 100644 --- a/include/mmc.h +++ b/include/mmc.h @@ -415,7 +415,6 @@ struct mmc *find_mmc_device(int dev_num); int mmc_set_dev(int dev_num); void print_mmc_devices(char separator); int get_mmc_num(void); -int mmc_switch_part(int dev_num, unsigned int part_num); int mmc_hwpart_config(struct mmc *mmc, const struct mmc_hwpart_conf *conf, enum mmc_hwpart_conf_mode mode); int mmc_getcd(struct mmc *mmc); From cd0fb55b640b2991c1d29122d252a360037ed903 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 1 May 2016 13:52:30 -0600 Subject: [PATCH 089/162] dm: blk: Add functions to select a hardware partition The block device uclass does not currently support selecting a particular hardware partition but this is needed for MMC. Add it so that the blk API can support MMC properly. Signed-off-by: Simon Glass --- drivers/block/blk-uclass.c | 29 +++++++++++++++++++++++++++++ include/blk.h | 30 ++++++++++++++++++++++++++++++ 2 files changed, 59 insertions(+) diff --git a/drivers/block/blk-uclass.c b/drivers/block/blk-uclass.c index a37239ee50..6ba1026f58 100644 --- a/drivers/block/blk-uclass.c +++ b/drivers/block/blk-uclass.c @@ -165,6 +165,18 @@ static int get_desc(enum if_type if_type, int devnum, struct blk_desc **descp) return found_more ? -ENOENT : -ENODEV; } +int blk_select_hwpart_devnum(enum if_type if_type, int devnum, int hwpart) +{ + struct udevice *dev; + int ret; + + ret = blk_get_device(if_type, devnum, &dev); + if (ret) + return ret; + + return blk_select_hwpart(dev, hwpart); +} + int blk_list_part(enum if_type if_type) { struct blk_desc *desc; @@ -291,6 +303,23 @@ ulong blk_write_devnum(enum if_type if_type, int devnum, lbaint_t start, return blk_dwrite(desc, start, blkcnt, buffer); } +int blk_select_hwpart(struct udevice *dev, int hwpart) +{ + const struct blk_ops *ops = blk_get_ops(dev); + + if (!ops) + return -ENOSYS; + if (!ops->select_hwpart) + return 0; + + return ops->select_hwpart(dev, hwpart); +} + +int blk_dselect_hwpart(struct blk_desc *desc, int hwpart) +{ + return blk_select_hwpart(desc->bdev, hwpart); +} + int blk_first_device(int if_type, struct udevice **devp) { struct blk_desc *desc; diff --git a/include/blk.h b/include/blk.h index 82b2c1a706..3fa373e208 100644 --- a/include/blk.h +++ b/include/blk.h @@ -211,6 +211,25 @@ struct blk_ops { */ unsigned long (*erase)(struct udevice *dev, lbaint_t start, lbaint_t blkcnt); + + /** + * select_hwpart() - select a particular hardware partition + * + * Some devices (e.g. MMC) can support partitioning at the hardware + * level. This is quite separate from the normal idea of + * software-based partitions. MMC hardware partitions must be + * explicitly selected. Once selected only the region of the device + * covered by that partition is accessible. + * + * The MMC standard provides for two boot partitions (numbered 1 and 2), + * rpmb (3), and up to 4 addition general-purpose partitions (4-7). + * + * @desc: Block device to update + * @hwpart: Hardware partition number to select. 0 means the raw + * device, 1 is the first partition, 2 is the second, etc. + * @return 0 if OK, -ve on error + */ + int (*select_hwpart)(struct udevice *dev, int hwpart); }; #define blk_get_ops(dev) ((struct blk_ops *)(dev)->driver->ops) @@ -329,6 +348,17 @@ int blk_unbind_all(int if_type); */ int blk_find_max_devnum(enum if_type if_type); +/** + * blk_select_hwpart() - select a hardware partition + * + * Select a hardware partition if the device supports it (typically MMC does) + * + * @dev: Device to update + * @hwpart: Partition number to select + * @return 0 if OK, -ve on error + */ +int blk_select_hwpart(struct udevice *dev, int hwpart); + #else #include /* From 1fde473da7a5de1e6ad1c72d1b84763642bb1a9f Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 1 May 2016 13:52:31 -0600 Subject: [PATCH 090/162] dm: part: Use the legacy block driver for hardware partition support Drop use of the table in part.c for this feature. Signed-off-by: Simon Glass --- disk/part.c | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/disk/part.c b/disk/part.c index e635d90864..db5dd5d2f9 100644 --- a/disk/part.c +++ b/disk/part.c @@ -71,9 +71,7 @@ static struct part_driver *part_driver_lookup_type(int part_type) static struct blk_desc *get_dev_hwpart(const char *ifname, int dev, int hwpart) { const struct block_drvr *drvr = block_drvr; - int (*select_hwpart)(int dev_num, int hwpart); char *name; - int ret; if (!ifname) return NULL; @@ -84,11 +82,8 @@ static struct blk_desc *get_dev_hwpart(const char *ifname, int dev, int hwpart) #endif while (drvr->name) { name = drvr->name; - select_hwpart = drvr->select_hwpart; #ifdef CONFIG_NEEDS_MANUAL_RELOC name += gd->reloc_off; - if (select_hwpart) - select_hwpart += gd->reloc_off; #endif if (strncmp(ifname, name, strlen(name)) == 0) { struct blk_desc *dev_desc; @@ -96,12 +91,7 @@ static struct blk_desc *get_dev_hwpart(const char *ifname, int dev, int hwpart) dev_desc = blk_get_devnum_by_typename(name, dev); if (!dev_desc) return NULL; - if (hwpart == 0 && !select_hwpart) - return dev_desc; - if (!select_hwpart) - return NULL; - ret = select_hwpart(dev_desc->devnum, hwpart); - if (ret < 0) + if (blk_dselect_hwpart(dev_desc, hwpart)) return NULL; return dev_desc; } From 6dd9faf8f97e1aad9961a480775612f6cbde27de Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 1 May 2016 13:52:32 -0600 Subject: [PATCH 091/162] dm: part: Drop the block_drvr table This is not needed since we can use the functions provided by the legacy block device support. Signed-off-by: Simon Glass --- disk/part.c | 67 ++++++++------------------------------- lib/efi_loader/efi_disk.c | 27 +++++++++------- 2 files changed, 30 insertions(+), 64 deletions(-) diff --git a/disk/part.c b/disk/part.c index db5dd5d2f9..3039f5f235 100644 --- a/disk/part.c +++ b/disk/part.c @@ -21,34 +21,6 @@ #define PRINTF(fmt,args...) #endif -const struct block_drvr block_drvr[] = { -#if defined(CONFIG_CMD_IDE) - { .name = "ide", }, -#endif -#if defined(CONFIG_CMD_SATA) - {.name = "sata", }, -#endif -#if defined(CONFIG_SCSI) - { .name = "scsi", }, -#endif -#if defined(CONFIG_CMD_USB) && defined(CONFIG_USB_STORAGE) - { .name = "usb", }, -#endif -#if defined(CONFIG_MMC) - { - .name = "mmc", - .select_hwpart = mmc_select_hwpart, - }, -#endif -#if defined(CONFIG_SYSTEMACE) - { .name = "ace", }, -#endif -#if defined(CONFIG_SANDBOX) - { .name = "host", }, -#endif - { }, -}; - DECLARE_GLOBAL_DATA_PTR; #ifdef HAVE_BLOCK_DEVICE @@ -70,34 +42,23 @@ static struct part_driver *part_driver_lookup_type(int part_type) static struct blk_desc *get_dev_hwpart(const char *ifname, int dev, int hwpart) { - const struct block_drvr *drvr = block_drvr; - char *name; + struct blk_desc *dev_desc; + int ret; - if (!ifname) + dev_desc = blk_get_devnum_by_typename(ifname, dev); + if (!dev_desc) { + debug("%s: No device for iface '%s', dev %d\n", __func__, + ifname, dev); return NULL; - - name = drvr->name; -#ifdef CONFIG_NEEDS_MANUAL_RELOC - name += gd->reloc_off; -#endif - while (drvr->name) { - name = drvr->name; -#ifdef CONFIG_NEEDS_MANUAL_RELOC - name += gd->reloc_off; -#endif - if (strncmp(ifname, name, strlen(name)) == 0) { - struct blk_desc *dev_desc; - - dev_desc = blk_get_devnum_by_typename(name, dev); - if (!dev_desc) - return NULL; - if (blk_dselect_hwpart(dev_desc, hwpart)) - return NULL; - return dev_desc; - } - drvr++; } - return NULL; + ret = blk_dselect_hwpart(dev_desc, hwpart); + if (ret) { + debug("%s: Failed to select h/w partition: err-%d\n", __func__, + ret); + return NULL; + } + + return dev_desc; } struct blk_desc *blk_get_dev(const char *ifname, int dev) diff --git a/lib/efi_loader/efi_disk.c b/lib/efi_loader/efi_disk.c index 28e5b7fce5..075fd34014 100644 --- a/lib/efi_loader/efi_disk.c +++ b/lib/efi_loader/efi_disk.c @@ -7,6 +7,7 @@ */ #include +#include #include #include #include @@ -142,7 +143,7 @@ static const struct efi_block_io block_io_disk_template = { }; static void efi_disk_add_dev(char *name, - const struct block_drvr *cur_drvr, + const struct blk_driver *cur_drvr, const struct blk_desc *desc, int dev_index, lbaint_t offset) @@ -160,7 +161,7 @@ static void efi_disk_add_dev(char *name, diskobj->parent.protocols[1].open = efi_disk_open_dp; diskobj->parent.handle = diskobj; diskobj->ops = block_io_disk_template; - diskobj->ifname = cur_drvr->name; + diskobj->ifname = cur_drvr->if_typename; diskobj->dev_index = dev_index; diskobj->offset = offset; @@ -189,7 +190,7 @@ static void efi_disk_add_dev(char *name, } static int efi_disk_create_eltorito(struct blk_desc *desc, - const struct block_drvr *cur_drvr, + const struct blk_driver *cur_drvr, int diskid) { int disks = 0; @@ -202,8 +203,8 @@ static int efi_disk_create_eltorito(struct blk_desc *desc, return 0; while (!part_get_info(desc, part, &info)) { - snprintf(devname, sizeof(devname), "%s%d:%d", cur_drvr->name, - diskid, part); + snprintf(devname, sizeof(devname), "%s%d:%d", + cur_drvr->if_typename, diskid, part); efi_disk_add_dev(devname, cur_drvr, desc, diskid, info.start); part++; disks++; @@ -222,25 +223,29 @@ static int efi_disk_create_eltorito(struct blk_desc *desc, */ int efi_disk_register(void) { - const struct block_drvr *cur_drvr; - int i; + const struct blk_driver *cur_drvr; + int i, if_type; int disks = 0; /* Search for all available disk devices */ - for (cur_drvr = block_drvr; cur_drvr->name; cur_drvr++) { - printf("Scanning disks on %s...\n", cur_drvr->name); + for (if_type = 0; if_type < IF_TYPE_COUNT; if_type++) { + cur_drvr = blk_driver_lookup_type(if_type); + if (!cur_drvr) + continue; + + printf("Scanning disks on %s...\n", cur_drvr->if_typename); for (i = 0; i < 4; i++) { struct blk_desc *desc; char devname[32] = { 0 }; /* dp->str is u16[32] long */ - desc = blk_get_dev(cur_drvr->name, i); + desc = blk_get_devnum_by_type(if_type, i); if (!desc) continue; if (desc->type == DEV_TYPE_UNKNOWN) continue; snprintf(devname, sizeof(devname), "%s%d", - cur_drvr->name, i); + cur_drvr->if_typename, i); efi_disk_add_dev(devname, cur_drvr, desc, i, 0); disks++; From b6694a33c45530e4c260c7fd6c77cc8472c9412f Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 1 May 2016 13:52:33 -0600 Subject: [PATCH 092/162] dm: blk: Add a comment as to why the bdev member is needed This member should be explained, since it is not obvious why it is needed. Add a comment. Signed-off-by: Simon Glass --- include/blk.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/include/blk.h b/include/blk.h index 3fa373e208..66a1c55cc8 100644 --- a/include/blk.h +++ b/include/blk.h @@ -63,6 +63,11 @@ struct blk_desc { char product[20+1]; /* IDE Serial no, SCSI product */ char revision[8+1]; /* firmware revision */ #ifdef CONFIG_BLK + /* + * For now we have a few functions which take struct blk_desc as a + * parameter. This field allows them to look up the associated + * device. Once these functions are removed we can drop this field. + */ struct udevice *bdev; #else unsigned long (*block_read)(struct blk_desc *block_dev, From cffe5d86cfe853ae9271d37522f8bc5795cc4c69 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 1 May 2016 13:52:34 -0600 Subject: [PATCH 093/162] dm: mmc: Set up the device pointer when using the MMC uclass Update the existing drivers to set up this new pointer. This will be required by the MMC uclass. Signed-off-by: Simon Glass --- drivers/mmc/omap_hsmmc.c | 1 + drivers/mmc/pic32_sdhci.c | 7 ++++++- drivers/mmc/rockchip_dw_mmc.c | 1 + drivers/mmc/socfpga_dw_mmc.c | 1 + drivers/mmc/uniphier-sd.c | 1 + drivers/mmc/zynq_sdhci.c | 1 + include/mmc.h | 3 +++ 7 files changed, 14 insertions(+), 1 deletion(-) diff --git a/drivers/mmc/omap_hsmmc.c b/drivers/mmc/omap_hsmmc.c index 85a832bd42..be34057ea2 100644 --- a/drivers/mmc/omap_hsmmc.c +++ b/drivers/mmc/omap_hsmmc.c @@ -825,6 +825,7 @@ static int omap_hsmmc_probe(struct udevice *dev) gpio_request_by_name(dev, "wp-gpios", 0, &priv->wp_gpio, GPIOD_IS_IN); #endif + mmc->dev = dev; upriv->mmc = mmc; return 0; diff --git a/drivers/mmc/pic32_sdhci.c b/drivers/mmc/pic32_sdhci.c index e03d6dd517..abe74293ed 100644 --- a/drivers/mmc/pic32_sdhci.c +++ b/drivers/mmc/pic32_sdhci.c @@ -41,7 +41,12 @@ static int pic32_sdhci_probe(struct udevice *dev) return ret; } - return add_sdhci(host, f_min_max[1], f_min_max[0]); + ret = add_sdhci(host, f_min_max[1], f_min_max[0]); + if (ret) + return ret; + host->mmc->dev = dev; + + return 0; } static const struct udevice_id pic32_sdhci_ids[] = { diff --git a/drivers/mmc/rockchip_dw_mmc.c b/drivers/mmc/rockchip_dw_mmc.c index cb9e1048d0..0a261c51a8 100644 --- a/drivers/mmc/rockchip_dw_mmc.c +++ b/drivers/mmc/rockchip_dw_mmc.c @@ -104,6 +104,7 @@ static int rockchip_dwmmc_probe(struct udevice *dev) if (ret) return ret; + host->mmc->dev = dev; upriv->mmc = host->mmc; return 0; diff --git a/drivers/mmc/socfpga_dw_mmc.c b/drivers/mmc/socfpga_dw_mmc.c index 097db81b05..6a0e9719b8 100644 --- a/drivers/mmc/socfpga_dw_mmc.c +++ b/drivers/mmc/socfpga_dw_mmc.c @@ -108,6 +108,7 @@ static int socfpga_dwmmc_probe(struct udevice *dev) return ret; upriv->mmc = host->mmc; + host->mmc->dev = dev; return 0; } diff --git a/drivers/mmc/uniphier-sd.c b/drivers/mmc/uniphier-sd.c index 81a80cdbc2..4978cca76d 100644 --- a/drivers/mmc/uniphier-sd.c +++ b/drivers/mmc/uniphier-sd.c @@ -725,6 +725,7 @@ int uniphier_sd_probe(struct udevice *dev) return -EIO; upriv->mmc = priv->mmc; + priv->mmc->dev = dev; return 0; } diff --git a/drivers/mmc/zynq_sdhci.c b/drivers/mmc/zynq_sdhci.c index b59feca80b..d405929b64 100644 --- a/drivers/mmc/zynq_sdhci.c +++ b/drivers/mmc/zynq_sdhci.c @@ -35,6 +35,7 @@ static int arasan_sdhci_probe(struct udevice *dev) CONFIG_ZYNQ_SDHCI_MIN_FREQ); upriv->mmc = host->mmc; + host->mmc->dev = dev; return 0; } diff --git a/include/mmc.h b/include/mmc.h index f01674d9fc..6d1f05c328 100644 --- a/include/mmc.h +++ b/include/mmc.h @@ -381,6 +381,9 @@ struct mmc { char init_in_progress; /* 1 if we have done mmc_start_init() */ char preinit; /* start init as early as possible */ int ddr_mode; +#ifdef CONFIG_DM_MMC + struct udevice *dev; /* Device for this MMC controller */ +#endif }; struct mmc_hwpart_conf { From c40fdca6b7db469d3982cc44fd68a269adb41b25 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 1 May 2016 13:52:35 -0600 Subject: [PATCH 094/162] dm: mmc: Move the device list into a separate file At present the MMC subsystem maintains its own list of MMC devices. This cannot work with driver model, which needs to maintain this itself. Move the list code into a separate 'legacy' file. The core MMC code remains, and will be shared with the driver-model implementation. Signed-off-by: Simon Glass --- cmd/mmc.c | 8 +- drivers/mmc/Makefile | 4 + drivers/mmc/mmc.c | 149 +++++++++----------------------------- drivers/mmc/mmc_legacy.c | 108 +++++++++++++++++++++++++++ drivers/mmc/mmc_private.h | 24 ++++++ drivers/mmc/mmc_write.c | 4 +- 6 files changed, 176 insertions(+), 121 deletions(-) create mode 100644 drivers/mmc/mmc_legacy.c diff --git a/cmd/mmc.c b/cmd/mmc.c index 8695c19187..eb4a547a97 100644 --- a/cmd/mmc.c +++ b/cmd/mmc.c @@ -348,7 +348,7 @@ static int do_mmc_read(cmd_tbl_t *cmdtp, int flag, printf("\nMMC read: dev # %d, block # %d, count %d ... ", curr_device, blk, cnt); - n = blk_dread(&mmc->block_dev, blk, cnt, addr); + n = blk_dread(mmc_get_blk_desc(mmc), blk, cnt, addr); /* flush cache after read */ flush_cache((ulong)addr, cnt * 512); /* FIXME */ printf("%d blocks read: %s\n", n, (n == cnt) ? "OK" : "ERROR"); @@ -380,7 +380,7 @@ static int do_mmc_write(cmd_tbl_t *cmdtp, int flag, printf("Error: card is write protected!\n"); return CMD_RET_FAILURE; } - n = blk_dwrite(&mmc->block_dev, blk, cnt, addr); + n = blk_dwrite(mmc_get_blk_desc(mmc), blk, cnt, addr); printf("%d blocks written: %s\n", n, (n == cnt) ? "OK" : "ERROR"); return (n == cnt) ? CMD_RET_SUCCESS : CMD_RET_FAILURE; @@ -408,7 +408,7 @@ static int do_mmc_erase(cmd_tbl_t *cmdtp, int flag, printf("Error: card is write protected!\n"); return CMD_RET_FAILURE; } - n = blk_derase(&mmc->block_dev, blk, cnt); + n = blk_derase(mmc_get_blk_desc(mmc), blk, cnt); printf("%d blocks erased: %s\n", n, (n == cnt) ? "OK" : "ERROR"); return (n == cnt) ? CMD_RET_SUCCESS : CMD_RET_FAILURE; @@ -480,7 +480,7 @@ static int do_mmc_dev(cmd_tbl_t *cmdtp, int flag, printf("mmc%d is current device\n", curr_device); else printf("mmc%d(part %d) is current device\n", - curr_device, mmc->block_dev.hwpart); + curr_device, mmc_get_blk_desc(mmc)->hwpart); return CMD_RET_SUCCESS; } diff --git a/drivers/mmc/Makefile b/drivers/mmc/Makefile index 585aaf3115..624164902d 100644 --- a/drivers/mmc/Makefile +++ b/drivers/mmc/Makefile @@ -7,6 +7,10 @@ obj-$(CONFIG_DM_MMC) += mmc-uclass.o +ifndef CONFIG_BLK +obj-$(CONFIG_GENERIC_MMC) += mmc_legacy.o +endif + obj-$(CONFIG_ARM_PL180_MMCI) += arm_pl180_mmci.o obj-$(CONFIG_ATMEL_SDHCI) += atmel_sdhci.o obj-$(CONFIG_BCM2835_SDHCI) += bcm2835_sdhci.o diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c index 7322f33404..48aedc212c 100644 --- a/drivers/mmc/mmc.c +++ b/drivers/mmc/mmc.c @@ -21,14 +21,6 @@ #include #include "mmc_private.h" -static struct list_head mmc_devices; -static int cur_dev_num = -1; - -struct blk_desc *mmc_get_blk_desc(struct mmc *mmc) -{ - return &mmc->block_dev; -} - __weak int board_mmc_getwp(struct mmc *mmc) { return -1; @@ -183,25 +175,6 @@ int mmc_set_blocklen(struct mmc *mmc, int len) return mmc_send_cmd(mmc, &cmd, NULL); } -struct mmc *find_mmc_device(int dev_num) -{ - struct mmc *m; - struct list_head *entry; - - list_for_each(entry, &mmc_devices) { - m = list_entry(entry, struct mmc, link); - - if (m->block_dev.devnum == dev_num) - return m; - } - -#if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT) - printf("MMC Device %d not found\n", dev_num); -#endif - - return NULL; -} - static int mmc_read_blocks(struct mmc *mmc, void *dst, lbaint_t start, lbaint_t blkcnt) { @@ -261,10 +234,10 @@ static ulong mmc_bread(struct blk_desc *block_dev, lbaint_t start, if (err < 0) return 0; - if ((start + blkcnt) > mmc->block_dev.lba) { + if ((start + blkcnt) > block_dev->lba) { #if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT) printf("MMC: block number 0x" LBAF " exceeds max(0x" LBAF ")\n", - start + blkcnt, mmc->block_dev.lba); + start + blkcnt, block_dev->lba); #endif return 0; } @@ -582,7 +555,7 @@ static int mmc_set_capacity(struct mmc *mmc, int part_num) return -1; } - mmc->block_dev.lba = lldiv(mmc->capacity, mmc->read_bl_len); + mmc_get_blk_desc(mmc)->lba = lldiv(mmc->capacity, mmc->read_bl_len); return 0; } @@ -1062,6 +1035,7 @@ static int mmc_startup(struct mmc *mmc) int timeout = 1000; bool has_parts = false; bool part_completed; + struct blk_desc *bdesc; #ifdef CONFIG_MMC_SPI_CRC_ON if (mmc_host_is_spi(mmc)) { /* enable CRC check for spi */ @@ -1358,7 +1332,7 @@ static int mmc_startup(struct mmc *mmc) mmc->wr_rel_set = ext_csd[EXT_CSD_WR_REL_SET]; } - err = mmc_set_capacity(mmc, mmc->block_dev.hwpart); + err = mmc_set_capacity(mmc, mmc_get_blk_desc(mmc)->hwpart); if (err) return err; @@ -1498,31 +1472,32 @@ static int mmc_startup(struct mmc *mmc) } /* fill in device description */ - mmc->block_dev.lun = 0; - mmc->block_dev.hwpart = 0; - mmc->block_dev.type = 0; - mmc->block_dev.blksz = mmc->read_bl_len; - mmc->block_dev.log2blksz = LOG2(mmc->block_dev.blksz); - mmc->block_dev.lba = lldiv(mmc->capacity, mmc->read_bl_len); + bdesc = mmc_get_blk_desc(mmc); + bdesc->lun = 0; + bdesc->hwpart = 0; + bdesc->type = 0; + bdesc->blksz = mmc->read_bl_len; + bdesc->log2blksz = LOG2(bdesc->blksz); + bdesc->lba = lldiv(mmc->capacity, mmc->read_bl_len); #if !defined(CONFIG_SPL_BUILD) || \ (defined(CONFIG_SPL_LIBCOMMON_SUPPORT) && \ !defined(CONFIG_USE_TINY_PRINTF)) - sprintf(mmc->block_dev.vendor, "Man %06x Snr %04x%04x", + sprintf(bdesc->vendor, "Man %06x Snr %04x%04x", mmc->cid[0] >> 24, (mmc->cid[2] & 0xffff), (mmc->cid[3] >> 16) & 0xffff); - sprintf(mmc->block_dev.product, "%c%c%c%c%c%c", mmc->cid[0] & 0xff, + sprintf(bdesc->product, "%c%c%c%c%c%c", mmc->cid[0] & 0xff, (mmc->cid[1] >> 24), (mmc->cid[1] >> 16) & 0xff, (mmc->cid[1] >> 8) & 0xff, mmc->cid[1] & 0xff, (mmc->cid[2] >> 24) & 0xff); - sprintf(mmc->block_dev.revision, "%d.%d", (mmc->cid[2] >> 20) & 0xf, + sprintf(bdesc->revision, "%d.%d", (mmc->cid[2] >> 20) & 0xf, (mmc->cid[2] >> 16) & 0xf); #else - mmc->block_dev.vendor[0] = 0; - mmc->block_dev.product[0] = 0; - mmc->block_dev.revision[0] = 0; + bdesc->vendor[0] = 0; + bdesc->product[0] = 0; + bdesc->revision[0] = 0; #endif #if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBDISK_SUPPORT) - part_init(&mmc->block_dev); + part_init(bdesc); #endif return 0; @@ -1562,6 +1537,7 @@ int __deprecated mmc_register(struct mmc *mmc) struct mmc *mmc_create(const struct mmc_config *cfg, void *priv) { + struct blk_desc *bdesc; struct mmc *mmc; /* quick validation */ @@ -1582,19 +1558,17 @@ struct mmc *mmc_create(const struct mmc_config *cfg, void *priv) mmc->dsr_imp = 0; mmc->dsr = 0xffffffff; /* Setup the universal parts of the block interface just once */ - mmc->block_dev.if_type = IF_TYPE_MMC; - mmc->block_dev.devnum = cur_dev_num++; - mmc->block_dev.removable = 1; - mmc->block_dev.block_read = mmc_bread; - mmc->block_dev.block_write = mmc_bwrite; - mmc->block_dev.block_erase = mmc_berase; + bdesc = mmc_get_blk_desc(mmc); + bdesc->if_type = IF_TYPE_MMC; + bdesc->removable = 1; + bdesc->devnum = mmc_get_next_devnum(); + bdesc->block_read = mmc_bread; + bdesc->block_write = mmc_bwrite; + bdesc->block_erase = mmc_berase; /* setup initial part type */ - mmc->block_dev.part_type = mmc->cfg->part_type; - - INIT_LIST_HEAD(&mmc->link); - - list_add_tail(&mmc->link, &mmc_devices); + bdesc->part_type = mmc->cfg->part_type; + mmc_list_add(mmc); return mmc; } @@ -1664,7 +1638,7 @@ int mmc_start_init(struct mmc *mmc) return err; /* The internal partition reset to user partition(0) at every CMD0*/ - mmc->block_dev.hwpart = 0; + mmc_get_blk_desc(mmc)->hwpart = 0; /* Test for SD version 2 */ err = mmc_send_if_cond(mmc); @@ -1744,66 +1718,11 @@ __weak int board_mmc_init(bd_t *bis) return -1; } -#if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT) - -void print_mmc_devices(char separator) -{ - struct mmc *m; - struct list_head *entry; - char *mmc_type; - - list_for_each(entry, &mmc_devices) { - m = list_entry(entry, struct mmc, link); - - if (m->has_init) - mmc_type = IS_SD(m) ? "SD" : "eMMC"; - else - mmc_type = NULL; - - printf("%s: %d", m->cfg->name, m->block_dev.devnum); - if (mmc_type) - printf(" (%s)", mmc_type); - - if (entry->next != &mmc_devices) { - printf("%c", separator); - if (separator != '\n') - puts (" "); - } - } - - printf("\n"); -} - -#else -void print_mmc_devices(char separator) { } -#endif - -int get_mmc_num(void) -{ - return cur_dev_num; -} - void mmc_set_preinit(struct mmc *mmc, int preinit) { mmc->preinit = preinit; } -static void do_preinit(void) -{ - struct mmc *m; - struct list_head *entry; - - list_for_each(entry, &mmc_devices) { - m = list_entry(entry, struct mmc, link); - -#ifdef CONFIG_FSL_ESDHC_ADAPTER_IDENT - mmc_set_preinit(m, 1); -#endif - if (m->preinit) - mmc_start_init(m); - } -} - #if defined(CONFIG_DM_MMC) && defined(CONFIG_SPL_BUILD) static int mmc_probe(bd_t *bis) { @@ -1856,9 +1775,9 @@ int mmc_initialize(bd_t *bis) return 0; initialized = 1; - INIT_LIST_HEAD (&mmc_devices); - cur_dev_num = 0; - +#ifndef CONFIG_BLK + mmc_list_init(); +#endif ret = mmc_probe(bis); if (ret) return ret; @@ -1867,7 +1786,7 @@ int mmc_initialize(bd_t *bis) print_mmc_devices(','); #endif - do_preinit(); + mmc_do_preinit(); return 0; } diff --git a/drivers/mmc/mmc_legacy.c b/drivers/mmc/mmc_legacy.c new file mode 100644 index 0000000000..3ec649f2b8 --- /dev/null +++ b/drivers/mmc/mmc_legacy.c @@ -0,0 +1,108 @@ +/* + * Copyright (C) 2016 Google, Inc + * Written by Simon Glass + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include + +static struct list_head mmc_devices; +static int cur_dev_num = -1; + +struct mmc *find_mmc_device(int dev_num) +{ + struct mmc *m; + struct list_head *entry; + + list_for_each(entry, &mmc_devices) { + m = list_entry(entry, struct mmc, link); + + if (m->block_dev.devnum == dev_num) + return m; + } + +#if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT) + printf("MMC Device %d not found\n", dev_num); +#endif + + return NULL; +} + +int mmc_get_next_devnum(void) +{ + return cur_dev_num++; +} + +struct blk_desc *mmc_get_blk_desc(struct mmc *mmc) +{ + return &mmc->block_dev; +} + +int get_mmc_num(void) +{ + return cur_dev_num; +} + +void mmc_do_preinit(void) +{ + struct mmc *m; + struct list_head *entry; + + list_for_each(entry, &mmc_devices) { + m = list_entry(entry, struct mmc, link); + +#ifdef CONFIG_FSL_ESDHC_ADAPTER_IDENT + mmc_set_preinit(m, 1); +#endif + if (m->preinit) + mmc_start_init(m); + } +} + +void mmc_list_init(void) +{ + INIT_LIST_HEAD(&mmc_devices); + cur_dev_num = 0; +} + +void mmc_list_add(struct mmc *mmc) +{ + INIT_LIST_HEAD(&mmc->link); + + list_add_tail(&mmc->link, &mmc_devices); +} + +#if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT) +void print_mmc_devices(char separator) +{ + struct mmc *m; + struct list_head *entry; + char *mmc_type; + + list_for_each(entry, &mmc_devices) { + m = list_entry(entry, struct mmc, link); + + if (m->has_init) + mmc_type = IS_SD(m) ? "SD" : "eMMC"; + else + mmc_type = NULL; + + printf("%s: %d", m->cfg->name, m->block_dev.devnum); + if (mmc_type) + printf(" (%s)", mmc_type); + + if (entry->next != &mmc_devices) { + printf("%c", separator); + if (separator != '\n') + puts(" "); + } + } + + printf("\n"); +} + +#else +void print_mmc_devices(char separator) { } +#endif diff --git a/drivers/mmc/mmc_private.h b/drivers/mmc/mmc_private.h index d3f6bfe123..6ec52fda05 100644 --- a/drivers/mmc/mmc_private.h +++ b/drivers/mmc/mmc_private.h @@ -46,4 +46,28 @@ static inline ulong mmc_bwrite(struct blk_desc *block_dev, lbaint_t start, #endif /* CONFIG_SPL_BUILD */ +/** + * mmc_get_next_devnum() - Get the next available MMC device number + * + * @return next available device number (0 = first), or -ve on error + */ +int mmc_get_next_devnum(void); + +/** + * mmc_do_preinit() - Get an MMC device ready for use + */ +void mmc_do_preinit(void); + +/** + * mmc_list_init() - Set up the list of MMC devices + */ +void mmc_list_init(void); + +/** + * mmc_list_add() - Add a new MMC device to the list of devices + * + * @mmc: Device to add + */ +void mmc_list_add(struct mmc *mmc); + #endif /* _MMC_PRIVATE_H_ */ diff --git a/drivers/mmc/mmc_write.c b/drivers/mmc/mmc_write.c index f4d42aaa76..bd07b20f5f 100644 --- a/drivers/mmc/mmc_write.c +++ b/drivers/mmc/mmc_write.c @@ -122,9 +122,9 @@ static ulong mmc_write_blocks(struct mmc *mmc, lbaint_t start, struct mmc_data data; int timeout = 1000; - if ((start + blkcnt) > mmc->block_dev.lba) { + if ((start + blkcnt) > mmc_get_blk_desc(mmc)->lba) { printf("MMC: block number 0x" LBAF " exceeds max(0x" LBAF ")\n", - start + blkcnt, mmc->block_dev.lba); + start + blkcnt, mmc_get_blk_desc(mmc)->lba); return 0; } From 1598dfcb101c2c3aaac68a4ac8fc9bdef2293eaa Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 1 May 2016 13:52:36 -0600 Subject: [PATCH 095/162] dm: blk: Use the correct error code for blk_get_device_by_str() Return -EINVAL instead of -1 in this function, to provide a more meaningful error. Signed-off-by: Simon Glass --- disk/part.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/disk/part.c b/disk/part.c index 3039f5f235..6a1c02d9fa 100644 --- a/disk/part.c +++ b/disk/part.c @@ -350,7 +350,7 @@ int blk_get_device_by_str(const char *ifname, const char *dev_hwpart_str, if (*ep) { printf("** Bad device specification %s %s **\n", ifname, dev_str); - dev = -1; + dev = -EINVAL; goto cleanup; } @@ -359,7 +359,7 @@ int blk_get_device_by_str(const char *ifname, const char *dev_hwpart_str, if (*ep) { printf("** Bad HW partition specification %s %s **\n", ifname, hwpart_str); - dev = -1; + dev = -EINVAL; goto cleanup; } } @@ -367,7 +367,7 @@ int blk_get_device_by_str(const char *ifname, const char *dev_hwpart_str, *dev_desc = get_dev_hwpart(ifname, dev, hwpart); if (!(*dev_desc) || ((*dev_desc)->type == DEV_TYPE_UNKNOWN)) { printf("** Bad device %s %s **\n", ifname, dev_hwpart_str); - dev = -1; + dev = -ENOENT; goto cleanup; } From fdbb139f0ce10325b44dd3ec76993f8c8e798395 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 1 May 2016 13:52:37 -0600 Subject: [PATCH 096/162] dm: mmc: Adjust mmc_switch_part() to use a struct mmc Instead of looking up the MMC device by number, just pass it in. This makes it possible to use this function with driver model. Signed-off-by: Simon Glass --- drivers/mmc/mmc.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c index 48aedc212c..4ba13a14e8 100644 --- a/drivers/mmc/mmc.c +++ b/drivers/mmc/mmc.c @@ -560,14 +560,10 @@ static int mmc_set_capacity(struct mmc *mmc, int part_num) return 0; } -int mmc_switch_part(int dev_num, unsigned int part_num) +static int mmc_switch_part(struct mmc *mmc, unsigned int part_num) { - struct mmc *mmc = find_mmc_device(dev_num); int ret; - if (!mmc) - return -1; - ret = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_PART_CONF, (mmc->part_config & ~PART_ACCESS_MASK) | (part_num & PART_ACCESS_MASK)); @@ -578,7 +574,7 @@ int mmc_switch_part(int dev_num, unsigned int part_num) */ if ((ret == 0) || ((ret == -ENODEV) && (part_num == 0))) { ret = mmc_set_capacity(mmc, part_num); - mmc->block_dev.hwpart = part_num; + mmc_get_blk_desc(mmc)->hwpart = part_num; } return ret; @@ -598,7 +594,7 @@ static int mmc_select_hwpartp(struct blk_desc *desc, int hwpart) if (mmc->part_config == MMCPART_NOAVAILABLE) return -EMEDIUMTYPE; - ret = mmc_switch_part(desc->devnum, hwpart); + ret = mmc_switch_part(mmc, hwpart); if (ret) return ret; @@ -619,7 +615,7 @@ int mmc_select_hwpart(int dev_num, int hwpart) if (mmc->part_config == MMCPART_NOAVAILABLE) return -EMEDIUMTYPE; - ret = mmc_switch_part(dev_num, hwpart); + ret = mmc_switch_part(mmc, hwpart); if (ret) return ret; From f8b7752e8f42c6f0bb8725f2488e398c849a7bf4 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 1 May 2016 13:52:38 -0600 Subject: [PATCH 097/162] dm: sandbox: Only enable the sandbox MMC driver when valid This driver will require generic MMC and block-device support in a future commit. To avoid test errors, make this change now. Signed-off-by: Simon Glass --- drivers/mmc/Makefile | 4 ++++ test/dm/Makefile | 4 +++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/mmc/Makefile b/drivers/mmc/Makefile index 624164902d..38a172be3a 100644 --- a/drivers/mmc/Makefile +++ b/drivers/mmc/Makefile @@ -38,7 +38,11 @@ obj-$(CONFIG_ROCKCHIP_DWMMC) += rockchip_dw_mmc.o obj-$(CONFIG_SUPPORT_EMMC_RPMB) += rpmb.o obj-$(CONFIG_S3C_SDI) += s3c_sdi.o obj-$(CONFIG_S5P_SDHCI) += s5p_sdhci.o +ifdef CONFIG_BLK +ifdef CONFIG_GENERIC_MMC obj-$(CONFIG_SANDBOX) += sandbox_mmc.o +endif +endif obj-$(CONFIG_SDHCI) += sdhci.o obj-$(CONFIG_SH_MMCIF) += sh_mmcif.o obj-$(CONFIG_SH_SDHI) += sh_sdhi.o diff --git a/test/dm/Makefile b/test/dm/Makefile index 9a11ae0a14..8ec391b6a4 100644 --- a/test/dm/Makefile +++ b/test/dm/Makefile @@ -21,7 +21,9 @@ obj-$(CONFIG_DM_ETH) += eth.o obj-$(CONFIG_DM_GPIO) += gpio.o obj-$(CONFIG_DM_I2C) += i2c.o obj-$(CONFIG_LED) += led.o -obj-$(CONFIG_DM_MMC) += mmc.o + +# Disable temporarily +# obj-$(CONFIG_DM_MMC) += mmc.o obj-$(CONFIG_DM_PCI) += pci.o obj-$(CONFIG_RAM) += ram.o obj-y += regmap.o From 8ef761ed4cda2d078b3d8b098d105472cbad8fb5 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 1 May 2016 13:52:39 -0600 Subject: [PATCH 098/162] dm: mmc: Implement the MMC functions for block devices Implement the functions in mmc_legacy.c for driver-model block devices, so that MMC can use driver model for these. This allows CONFIG_BLK to be enabled with DM_MMC. Signed-off-by: Simon Glass --- drivers/mmc/Makefile | 4 +- drivers/mmc/mmc-uclass.c | 106 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 109 insertions(+), 1 deletion(-) diff --git a/drivers/mmc/Makefile b/drivers/mmc/Makefile index 38a172be3a..3da4817a18 100644 --- a/drivers/mmc/Makefile +++ b/drivers/mmc/Makefile @@ -5,7 +5,9 @@ # SPDX-License-Identifier: GPL-2.0+ # -obj-$(CONFIG_DM_MMC) += mmc-uclass.o +ifdef CONFIG_DM_MMC +obj-$(CONFIG_GENERIC_MMC) += mmc-uclass.o +endif ifndef CONFIG_BLK obj-$(CONFIG_GENERIC_MMC) += mmc_legacy.o diff --git a/drivers/mmc/mmc-uclass.c b/drivers/mmc/mmc-uclass.c index 777489f5d8..1b967d982b 100644 --- a/drivers/mmc/mmc-uclass.c +++ b/drivers/mmc/mmc-uclass.c @@ -21,6 +21,112 @@ struct mmc *mmc_get_mmc_dev(struct udevice *dev) return upriv->mmc; } +#ifdef CONFIG_BLK +struct mmc *find_mmc_device(int dev_num) +{ + struct udevice *dev, *mmc_dev; + int ret; + + ret = blk_get_device(IF_TYPE_MMC, dev_num, &dev); + + if (ret) { +#if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT) + printf("MMC Device %d not found\n", dev_num); +#endif + return NULL; + } + + mmc_dev = dev_get_parent(dev); + + return mmc_get_mmc_dev(mmc_dev); +} + +int get_mmc_num(void) +{ + return max(blk_find_max_devnum(IF_TYPE_MMC), 0); +} + +int mmc_get_next_devnum(void) +{ + int ret; + + ret = get_mmc_num(); + if (ret < 0) + return ret; + + return ret + 1; +} + +struct blk_desc *mmc_get_blk_desc(struct mmc *mmc) +{ + struct blk_desc *desc; + struct udevice *dev; + + device_find_first_child(mmc->dev, &dev); + if (!dev) + return NULL; + desc = dev_get_uclass_platdata(dev); + + return desc; +} + +void mmc_do_preinit(void) +{ + struct udevice *dev; + struct uclass *uc; + int ret; + + ret = uclass_get(UCLASS_MMC, &uc); + if (ret) + return; + uclass_foreach_dev(dev, uc) { + struct mmc *m = mmc_get_mmc_dev(dev); + + if (!m) + continue; +#ifdef CONFIG_FSL_ESDHC_ADAPTER_IDENT + mmc_set_preinit(m, 1); +#endif + if (m->preinit) + mmc_start_init(m); + } +} + +#if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT) +void print_mmc_devices(char separator) +{ + struct udevice *dev; + char *mmc_type; + bool first = true; + + for (uclass_first_device(UCLASS_MMC, &dev); + dev; + uclass_next_device(&dev)) { + struct mmc *m = mmc_get_mmc_dev(dev); + + if (!first) { + printf("%c", separator); + if (separator != '\n') + puts(" "); + } + if (m->has_init) + mmc_type = IS_SD(m) ? "SD" : "eMMC"; + else + mmc_type = NULL; + + printf("%s: %d", m->cfg->name, mmc_get_blk_desc(m)->devnum); + if (mmc_type) + printf(" (%s)", mmc_type); + } + + printf("\n"); +} + +#else +void print_mmc_devices(char separator) { } +#endif +#endif /* CONFIG_BLK */ + U_BOOT_DRIVER(mmc) = { .name = "mmc", .id = UCLASS_MMC, From ad27dd5e13436b554f0f3cb9cd3e79634494072d Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 1 May 2016 13:52:40 -0600 Subject: [PATCH 099/162] dm: mmc: Add a way to bind MMC devices with driver model Binding an MMC device when CONFIG_BLK is enabled requires that a block device be bound as a child of the MMC device. Add a function to do this. The mmc_create() method will be used only when DM_BLK is disabled. Add an unbind method also. Signed-off-by: Simon Glass --- drivers/mmc/mmc.c | 48 +++++++++++++++++++++++++++++++++++++++++++++++ include/mmc.h | 22 ++++++++++++++++++++++ 2 files changed, 70 insertions(+) diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c index 4ba13a14e8..7183afcff2 100644 --- a/drivers/mmc/mmc.c +++ b/drivers/mmc/mmc.c @@ -1531,6 +1531,53 @@ int __deprecated mmc_register(struct mmc *mmc) return -1; } +#ifdef CONFIG_BLK +int mmc_bind(struct udevice *dev, struct mmc *mmc, const struct mmc_config *cfg) +{ + struct blk_desc *bdesc; + struct udevice *bdev; + int ret; + + ret = blk_create_devicef(dev, "mmc_blk", "blk", IF_TYPE_MMC, -1, 512, + 0, &bdev); + if (ret) { + debug("Cannot create block device\n"); + return ret; + } + bdesc = dev_get_uclass_platdata(bdev); + mmc->cfg = cfg; + mmc->priv = dev; + + /* the following chunk was from mmc_register() */ + + /* Setup dsr related values */ + mmc->dsr_imp = 0; + mmc->dsr = 0xffffffff; + /* Setup the universal parts of the block interface just once */ + bdesc->if_type = IF_TYPE_MMC; + bdesc->removable = 1; + + /* setup initial part type */ + bdesc->part_type = mmc->cfg->part_type; + mmc->dev = dev; + + return 0; +} + +int mmc_unbind(struct udevice *dev) +{ + struct udevice *bdev; + + device_find_first_child(dev, &bdev); + if (bdev) { + device_remove(bdev); + device_unbind(bdev); + } + + return 0; +} + +#else struct mmc *mmc_create(const struct mmc_config *cfg, void *priv) { struct blk_desc *bdesc; @@ -1574,6 +1621,7 @@ void mmc_destroy(struct mmc *mmc) /* only freeing memory for now */ free(mmc); } +#endif static int mmc_get_dev(int dev, struct blk_desc **descp) { diff --git a/include/mmc.h b/include/mmc.h index 6d1f05c328..fb8d9b2f55 100644 --- a/include/mmc.h +++ b/include/mmc.h @@ -409,7 +409,29 @@ enum mmc_hwpart_conf_mode { int mmc_register(struct mmc *mmc); struct mmc *mmc_create(const struct mmc_config *cfg, void *priv); + +/** + * mmc_bind() - Set up a new MMC device ready for probing + * + * A child block device is bound with the IF_TYPE_MMC interface type. This + * allows the device to be used with CONFIG_BLK + * + * @dev: MMC device to set up + * @mmc: MMC struct + * @cfg: MMC configuration + * @return 0 if OK, -ve on error + */ +int mmc_bind(struct udevice *dev, struct mmc *mmc, + const struct mmc_config *cfg); void mmc_destroy(struct mmc *mmc); + +/** + * mmc_unbind() - Unbind a MMC device's child block device + * + * @dev: MMC device + * @return 0 if OK, -ve on error + */ +int mmc_unbind(struct udevice *dev); int mmc_initialize(bd_t *bis); int mmc_init(struct mmc *mmc); int mmc_read(struct mmc *mmc, u64 src, uchar *dst, int size); From 33fb211dd2706e666db4008801dc0d5903fd82f6 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 1 May 2016 13:52:41 -0600 Subject: [PATCH 100/162] dm: mmc: Add support for driver-model block devices Add support for enabling CONFIG_BLK with MMC. This involves changing a few functions to use struct udevice and adding a MMC block device driver. Signed-off-by: Simon Glass --- drivers/mmc/mmc.c | 72 +++++++++++++++++++++++++++------------ drivers/mmc/mmc_private.h | 9 +++-- drivers/mmc/mmc_write.c | 9 +++++ include/mmc.h | 4 +++ include/part.h | 18 ---------- 5 files changed, 70 insertions(+), 42 deletions(-) diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c index 7183afcff2..74b3d68f87 100644 --- a/drivers/mmc/mmc.c +++ b/drivers/mmc/mmc.c @@ -216,9 +216,17 @@ static int mmc_read_blocks(struct mmc *mmc, void *dst, lbaint_t start, return blkcnt; } +#ifdef CONFIG_BLK +static ulong mmc_bread(struct udevice *dev, lbaint_t start, lbaint_t blkcnt, + void *dst) +#else static ulong mmc_bread(struct blk_desc *block_dev, lbaint_t start, lbaint_t blkcnt, void *dst) +#endif { +#ifdef CONFIG_BLK + struct blk_desc *block_dev = dev_get_uclass_platdata(dev); +#endif int dev_num = block_dev->devnum; int err; lbaint_t cur, blocks_todo = blkcnt; @@ -580,6 +588,27 @@ static int mmc_switch_part(struct mmc *mmc, unsigned int part_num) return ret; } +#ifdef CONFIG_BLK +static int mmc_select_hwpart(struct udevice *bdev, int hwpart) +{ + struct udevice *mmc_dev = dev_get_parent(bdev); + struct mmc *mmc = mmc_get_mmc_dev(mmc_dev); + struct blk_desc *desc = dev_get_uclass_platdata(bdev); + int ret; + + if (desc->hwpart == hwpart) + return 0; + + if (mmc->part_config == MMCPART_NOAVAILABLE) + return -EMEDIUMTYPE; + + ret = mmc_switch_part(mmc, hwpart); + if (ret) + return ret; + + return 0; +} +#else static int mmc_select_hwpartp(struct blk_desc *desc, int hwpart) { struct mmc *mmc = find_mmc_device(desc->devnum); @@ -600,27 +629,7 @@ static int mmc_select_hwpartp(struct blk_desc *desc, int hwpart) return 0; } - -int mmc_select_hwpart(int dev_num, int hwpart) -{ - struct mmc *mmc = find_mmc_device(dev_num); - int ret; - - if (!mmc) - return -ENODEV; - - if (mmc->block_dev.hwpart == hwpart) - return 0; - - if (mmc->part_config == MMCPART_NOAVAILABLE) - return -EMEDIUMTYPE; - - ret = mmc_switch_part(mmc, hwpart); - if (ret) - return ret; - - return 0; -} +#endif int mmc_hwpart_config(struct mmc *mmc, const struct mmc_hwpart_conf *conf, @@ -1554,7 +1563,6 @@ int mmc_bind(struct udevice *dev, struct mmc *mmc, const struct mmc_config *cfg) mmc->dsr_imp = 0; mmc->dsr = 0xffffffff; /* Setup the universal parts of the block interface just once */ - bdesc->if_type = IF_TYPE_MMC; bdesc->removable = 1; /* setup initial part type */ @@ -1623,6 +1631,7 @@ void mmc_destroy(struct mmc *mmc) } #endif +#ifndef CONFIG_BLK static int mmc_get_dev(int dev, struct blk_desc **descp) { struct mmc *mmc = find_mmc_device(dev); @@ -1638,6 +1647,7 @@ static int mmc_get_dev(int dev, struct blk_desc **descp) return 0; } +#endif /* board-specific MMC power initializations. */ __weak void board_mmc_power_init(void) @@ -1729,7 +1739,11 @@ int mmc_init(struct mmc *mmc) { int err = 0; unsigned start; +#ifdef CONFIG_DM_MMC + struct mmc_uclass_priv *upriv = dev_get_uclass_priv(mmc->dev); + upriv->mmc = mmc; +#endif if (mmc->has_init) return 0; @@ -1957,6 +1971,19 @@ int mmc_set_rst_n_function(struct mmc *mmc, u8 enable) } #endif +#ifdef CONFIG_BLK +static const struct blk_ops mmc_blk_ops = { + .read = mmc_bread, + .write = mmc_bwrite, + .select_hwpart = mmc_select_hwpart, +}; + +U_BOOT_DRIVER(mmc_blk) = { + .name = "mmc_blk", + .id = UCLASS_BLK, + .ops = &mmc_blk_ops, +}; +#else U_BOOT_LEGACY_BLK(mmc) = { .if_typename = "mmc", .if_type = IF_TYPE_MMC, @@ -1964,3 +1991,4 @@ U_BOOT_LEGACY_BLK(mmc) = { .get_dev = mmc_get_dev, .select_hwpart = mmc_select_hwpartp, }; +#endif diff --git a/drivers/mmc/mmc_private.h b/drivers/mmc/mmc_private.h index 6ec52fda05..27b9e5f56f 100644 --- a/drivers/mmc/mmc_private.h +++ b/drivers/mmc/mmc_private.h @@ -25,8 +25,13 @@ void mmc_adapter_card_type_ident(void); unsigned long mmc_berase(struct blk_desc *block_dev, lbaint_t start, lbaint_t blkcnt); -unsigned long mmc_bwrite(struct blk_desc *block_dev, lbaint_t start, - lbaint_t blkcnt, const void *src); +#ifdef CONFIG_BLK +ulong mmc_bwrite(struct udevice *dev, lbaint_t start, lbaint_t blkcnt, + const void *src); +#else +ulong mmc_bwrite(struct blk_desc *block_dev, lbaint_t start, lbaint_t blkcnt, + const void *src); +#endif #else /* CONFIG_SPL_BUILD */ diff --git a/drivers/mmc/mmc_write.c b/drivers/mmc/mmc_write.c index bd07b20f5f..0f8b5c79d7 100644 --- a/drivers/mmc/mmc_write.c +++ b/drivers/mmc/mmc_write.c @@ -9,6 +9,7 @@ #include #include +#include #include #include #include @@ -172,9 +173,17 @@ static ulong mmc_write_blocks(struct mmc *mmc, lbaint_t start, return blkcnt; } +#ifdef CONFIG_BLK +ulong mmc_bwrite(struct udevice *dev, lbaint_t start, lbaint_t blkcnt, + const void *src) +#else ulong mmc_bwrite(struct blk_desc *block_dev, lbaint_t start, lbaint_t blkcnt, const void *src) +#endif { +#ifdef CONFIG_BLK + struct blk_desc *block_dev = dev_get_uclass_platdata(dev); +#endif int dev_num = block_dev->devnum; lbaint_t cur, blocks_todo = blkcnt; int err; diff --git a/include/mmc.h b/include/mmc.h index fb8d9b2f55..a5c6573ddd 100644 --- a/include/mmc.h +++ b/include/mmc.h @@ -344,7 +344,9 @@ struct mmc_config { /* TODO struct mmc should be in mmc_private but it's hard to fix right now */ struct mmc { +#ifndef CONFIG_BLK struct list_head link; +#endif const struct mmc_config *cfg; /* provided configuration */ uint version; void *priv; @@ -376,7 +378,9 @@ struct mmc { u64 capacity_gp[4]; u64 enh_user_start; u64 enh_user_size; +#ifndef CONFIG_BLK struct blk_desc block_dev; +#endif char op_cond_pending; /* 1 if we are waiting on an op_cond command */ char init_in_progress; /* 1 if we have done mmc_start_init() */ char preinit; /* start init as early as possible */ diff --git a/include/part.h b/include/part.h index bc9dc64912..226b5be9df 100644 --- a/include/part.h +++ b/include/part.h @@ -73,23 +73,6 @@ typedef struct disk_partition { */ struct blk_desc *blk_get_dev(const char *ifname, int dev); -/** - * mmc_select_hwpart() - Select the MMC hardware partiion on an MMC device - * - * MMC devices can support partitioning at the hardware level. This is quite - * separate from the normal idea of software-based partitions. MMC hardware - * partitions must be explicitly selected. Once selected only the region of - * the device covered by that partition is accessible. - * - * The MMC standard provides for two boot partitions (numbered 1 and 2), - * rpmb (3), and up to 4 addition general-purpose partitions (4-7). - * - * @dev_num: Block device number (struct blk_desc->dev value) - * @hwpart: Hardware partition number to select. 0 means the raw device, - * 1 is the first partition, 2 is the second, etc. - * @return 0 if OK, other value for an error - */ -int mmc_select_hwpart(int dev_num, int hwpart); struct blk_desc *mg_disk_get_dev(int dev); int host_get_dev_err(int dev, struct blk_desc **blk_devp); @@ -167,7 +150,6 @@ extern const struct block_drvr block_drvr[]; #else static inline struct blk_desc *blk_get_dev(const char *ifname, int dev) { return NULL; } -static inline int mmc_select_hwpart(int dev_num, int hwpart) { return -1; } static inline struct blk_desc *mg_disk_get_dev(int dev) { return NULL; } static inline int part_get_info(struct blk_desc *dev_desc, int part, From f376a3cbbf34d3114d92789540ba2d2e9e904758 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 1 May 2016 13:52:42 -0600 Subject: [PATCH 101/162] dm: mmc: sandbox: Add an SD-card emulation Add an emulation of an SD card to sandbox, allowing MMC to be used in tests. The emulation is very simple, supporting only card detection and reading test data. Signed-off-by: Simon Glass --- drivers/mmc/Kconfig | 11 +++- drivers/mmc/sandbox_mmc.c | 134 +++++++++++++++++++++++++++++++++++++- 2 files changed, 143 insertions(+), 2 deletions(-) diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig index 4d3df11a1b..c80efc39a7 100644 --- a/drivers/mmc/Kconfig +++ b/drivers/mmc/Kconfig @@ -2,7 +2,7 @@ menu "MMC Host controller Support" config MMC bool "Enable MMC support" - depends on ARCH_SUNXI + depends on ARCH_SUNXI || SANDBOX help TODO: Move all architectures to use this option @@ -58,4 +58,13 @@ config MMC_UNIPHIER help This selects support for the SD/MMC Host Controller on UniPhier SoCs. +config SANDBOX_MMC + bool "Sandbox MMC support" + depends on MMC && SANDBOX + help + This select a dummy sandbox MMC driver. At present this does nothing + other than allow sandbox to be build with MMC support. This + improves build coverage for sandbox and makes it easier to detect + MMC build errors with sandbox. + endmenu diff --git a/drivers/mmc/sandbox_mmc.c b/drivers/mmc/sandbox_mmc.c index f4646a824f..7da059c43c 100644 --- a/drivers/mmc/sandbox_mmc.c +++ b/drivers/mmc/sandbox_mmc.c @@ -8,18 +8,150 @@ #include #include #include +#include #include #include DECLARE_GLOBAL_DATA_PTR; +struct sandbox_mmc_plat { + struct mmc_config cfg; + struct mmc mmc; +}; + +/** + * sandbox_mmc_send_cmd() - Emulate SD commands + * + * This emulate an SD card version 2. Single-block reads result in zero data. + * Multiple-block reads return a test string. + */ +static int sandbox_mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, + struct mmc_data *data) +{ + switch (cmd->cmdidx) { + case MMC_CMD_ALL_SEND_CID: + break; + case SD_CMD_SEND_RELATIVE_ADDR: + cmd->response[0] = 0 << 16; /* mmc->rca */ + case MMC_CMD_GO_IDLE_STATE: + break; + case SD_CMD_SEND_IF_COND: + cmd->response[0] = 0xaa; + break; + case MMC_CMD_SEND_STATUS: + cmd->response[0] = MMC_STATUS_RDY_FOR_DATA; + break; + case MMC_CMD_SELECT_CARD: + break; + case MMC_CMD_SEND_CSD: + cmd->response[0] = 0; + cmd->response[1] = 10 << 16; /* 1 << block_len */ + break; + case SD_CMD_SWITCH_FUNC: { + u32 *resp = (u32 *)data->dest; + + resp[7] = cpu_to_be32(SD_HIGHSPEED_BUSY); + break; + } + case MMC_CMD_READ_SINGLE_BLOCK: + memset(data->dest, '\0', data->blocksize); + break; + case MMC_CMD_READ_MULTIPLE_BLOCK: + strcpy(data->dest, "this is a test"); + break; + case MMC_CMD_STOP_TRANSMISSION: + break; + case SD_CMD_APP_SEND_OP_COND: + cmd->response[0] = OCR_BUSY | OCR_HCS; + cmd->response[1] = 0; + cmd->response[2] = 0; + break; + case MMC_CMD_APP_CMD: + break; + case MMC_CMD_SET_BLOCKLEN: + debug("block len %d\n", cmd->cmdarg); + break; + case SD_CMD_APP_SEND_SCR: { + u32 *scr = (u32 *)data->dest; + + scr[0] = cpu_to_be32(2 << 24 | 1 << 15); /* SD version 3 */ + break; + } + default: + debug("%s: Unknown command %d\n", __func__, cmd->cmdidx); + break; + } + + return 0; +} + +static void sandbox_mmc_set_ios(struct mmc *mmc) +{ +} + +static int sandbox_mmc_init(struct mmc *mmc) +{ + return 0; +} + +static int sandbox_mmc_getcd(struct mmc *mmc) +{ + return 1; +} + +static const struct mmc_ops sandbox_mmc_ops = { + .send_cmd = sandbox_mmc_send_cmd, + .set_ios = sandbox_mmc_set_ios, + .init = sandbox_mmc_init, + .getcd = sandbox_mmc_getcd, +}; + +int sandbox_mmc_probe(struct udevice *dev) +{ + struct sandbox_mmc_plat *plat = dev_get_platdata(dev); + + return mmc_init(&plat->mmc); +} + +int sandbox_mmc_bind(struct udevice *dev) +{ + struct sandbox_mmc_plat *plat = dev_get_platdata(dev); + struct mmc_config *cfg = &plat->cfg; + int ret; + + cfg->name = dev->name; + cfg->ops = &sandbox_mmc_ops; + cfg->host_caps = MMC_MODE_HS_52MHz | MMC_MODE_HS | MMC_MODE_8BIT; + cfg->voltages = MMC_VDD_165_195 | MMC_VDD_32_33 | MMC_VDD_33_34; + cfg->f_min = 1000000; + cfg->f_max = 52000000; + cfg->b_max = U32_MAX; + + ret = mmc_bind(dev, &plat->mmc, cfg); + if (ret) + return ret; + + return 0; +} + +int sandbox_mmc_unbind(struct udevice *dev) +{ + mmc_unbind(dev); + + return 0; +} + static const struct udevice_id sandbox_mmc_ids[] = { { .compatible = "sandbox,mmc" }, { } }; -U_BOOT_DRIVER(warm_mmc_sandbox) = { +U_BOOT_DRIVER(mmc_sandbox) = { .name = "mmc_sandbox", .id = UCLASS_MMC, .of_match = sandbox_mmc_ids, + .bind = sandbox_mmc_bind, + .unbind = sandbox_mmc_unbind, + .probe = sandbox_mmc_probe, + .platdata_auto_alloc_size = sizeof(struct sandbox_mmc_plat), }; From afa2c3122db1ef5243e717b84d698353da412d92 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 1 May 2016 13:52:43 -0600 Subject: [PATCH 102/162] dm: sandbox: mmc: Enable building MMC code for sandbox Enable building the MMC code for sandbox. This increases build coverage for sandbox. Signed-off-by: Simon Glass --- configs/sandbox_defconfig | 2 ++ include/configs/sandbox.h | 2 ++ test/dm/blk.c | 4 ++-- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig index afdf4a3ba7..aec2e538a1 100644 --- a/configs/sandbox_defconfig +++ b/configs/sandbox_defconfig @@ -1,4 +1,5 @@ CONFIG_SYS_MALLOC_F_LEN=0x2000 +CONFIG_MMC=y CONFIG_PCI=y CONFIG_DEFAULT_DEVICE_TREE="sandbox" CONFIG_I8042_KEYB=y @@ -97,6 +98,7 @@ CONFIG_PWRSEQ=y CONFIG_SPL_PWRSEQ=y CONFIG_RESET=y CONFIG_DM_MMC=y +CONFIG_SANDBOX_MMC=y CONFIG_SPI_FLASH_SANDBOX=y CONFIG_SPI_FLASH=y CONFIG_SPI_FLASH_ATMEL=y diff --git a/include/configs/sandbox.h b/include/configs/sandbox.h index c51d4cd737..23a0c40ca5 100644 --- a/include/configs/sandbox.h +++ b/include/configs/sandbox.h @@ -215,4 +215,6 @@ #define CONFIG_SYS_SYSTEMACE_WIDTH 16 #define CONFIG_SYS_SYSTEMACE_BASE 0 +#define CONFIG_GENERIC_MMC + #endif diff --git a/test/dm/blk.c b/test/dm/blk.c index f4ea32e83e..012bf4cab5 100644 --- a/test/dm/blk.c +++ b/test/dm/blk.c @@ -83,12 +83,12 @@ static int dm_test_blk_usb(struct unit_test_state *uts) ut_asserteq_ptr(usb_dev, dev_get_parent(dev)); /* Check we have one block device for each mass storage device */ - ut_asserteq(3, count_blk_devices()); + ut_asserteq(4, count_blk_devices()); /* Now go around again, making sure the old devices were unbound */ ut_assertok(usb_stop()); ut_assertok(usb_init()); - ut_asserteq(3, count_blk_devices()); + ut_asserteq(4, count_blk_devices()); ut_assertok(usb_stop()); return 0; From 341392dd115f1385c31bb0b034ec15f542730e30 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 1 May 2016 13:52:44 -0600 Subject: [PATCH 103/162] dm: mmc: test: Add tests for MMC Add a simple test which checks that a sandbox-emulated SD card can be used correctly. This tests plumbing through the MMC stack's block-device implementaion. Signed-off-by: Simon Glass --- test/dm/Makefile | 4 +--- test/dm/mmc.c | 19 +++++++++++++++++++ 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/test/dm/Makefile b/test/dm/Makefile index 8ec391b6a4..9a11ae0a14 100644 --- a/test/dm/Makefile +++ b/test/dm/Makefile @@ -21,9 +21,7 @@ obj-$(CONFIG_DM_ETH) += eth.o obj-$(CONFIG_DM_GPIO) += gpio.o obj-$(CONFIG_DM_I2C) += i2c.o obj-$(CONFIG_LED) += led.o - -# Disable temporarily -# obj-$(CONFIG_DM_MMC) += mmc.o +obj-$(CONFIG_DM_MMC) += mmc.o obj-$(CONFIG_DM_PCI) += pci.o obj-$(CONFIG_RAM) += ram.o obj-y += regmap.o diff --git a/test/dm/mmc.c b/test/dm/mmc.c index 046142322d..5bca4b79d5 100644 --- a/test/dm/mmc.c +++ b/test/dm/mmc.c @@ -25,3 +25,22 @@ static int dm_test_mmc_base(struct unit_test_state *uts) return 0; } DM_TEST(dm_test_mmc_base, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT); + +static int dm_test_mmc_blk(struct unit_test_state *uts) +{ + struct udevice *dev; + struct blk_desc *dev_desc; + char cmp[1024]; + + ut_assertok(uclass_get_device(UCLASS_MMC, 0, &dev)); + ut_assertok(blk_get_device_by_str("mmc", "0", &dev_desc)); + + /* Read a few blocks and look for the string we expect */ + ut_asserteq(512, dev_desc->blksz); + memset(cmp, '\0', sizeof(cmp)); + ut_asserteq(2, blk_dread(dev_desc, 0, 2, cmp)); + ut_assertok(strcmp(cmp, "this is a test")); + + return 0; +} +DM_TEST(dm_test_mmc_blk, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT); From 29b59353fe7cd62c74960b76e7b56bbc368429d2 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sat, 30 Apr 2016 14:45:42 +0200 Subject: [PATCH 104/162] arm: mvebu: a38x: Weed out floating point use For reason unknown, recently, the DDR init code writers are really fond of hiding some small floating point operating deep in their creations. This patch removes one from the Marvell A38x code. Instead of returning size of chip as float from ddr3_get_device_size() in GiB units, return it as int in MiB units. Since this would interfere with the huge switch code in ddr3_calc_mem_cs_size(), rework the code to match the change. Before this patch, the cs_mem_size variable could have these values: ( { 16, 32 } x { 8, 16 } x { 0.01, 0.5, 1, 2, 4, 8 } ) / 8 = { 0.000000, 0.001250, 0.002500, 0.005000, 0.062500, 0.125000, 0.250000, 0.500000, 1.000000, 2.000000, 4.000000, } The switch code checked for a subset of the resulting RAM sizes, which is in range 128 MiB ... 2048 MiB. With this patch, the cs_mem_size variable can have these values: ( { 16, 32 } x { 8, 16 } x { 0, 512, 1024, 2048, 4096, 8192 } ) / 8 = { 0, 64, 128, 256, 512, 1024, 2048, 4096 } To retain previous behavior, filter out 0 MiB (invalid size), 64 MiB and 4096 MiB options. Removing the floating point stuff also saves 1.5k from text segment: clearfog : spl/u-boot-spl:all -1592 spl/u-boot-spl:text -1592 Signed-off-by: Marek Vasut Cc: Dirk Eibach Cc: Stefan Roese Signed-off-by: Stefan Roese --- drivers/ddr/marvell/a38x/ddr3_init.c | 29 ++++++++++------------------ 1 file changed, 10 insertions(+), 19 deletions(-) diff --git a/drivers/ddr/marvell/a38x/ddr3_init.c b/drivers/ddr/marvell/a38x/ddr3_init.c index ee05f57f43..55baad498a 100644 --- a/drivers/ddr/marvell/a38x/ddr3_init.c +++ b/drivers/ddr/marvell/a38x/ddr3_init.c @@ -678,7 +678,7 @@ u32 ddr3_get_device_width(u32 cs) return (device_width == 0) ? 8 : 16; } -float ddr3_get_device_size(u32 cs) +static int ddr3_get_device_size(u32 cs) { u32 device_size_low, device_size_high, device_size; u32 data, cs_low_offset, cs_high_offset; @@ -695,15 +695,15 @@ float ddr3_get_device_size(u32 cs) switch (device_size) { case 0: - return 2; + return 2048; case 2: - return 0.5; + return 512; case 3: - return 1; + return 1024; case 4: - return 4; + return 4096; case 5: - return 8; + return 8192; case 1: default: DEBUG_INIT_C("Error: Wrong device size of Cs: ", cs, 1); @@ -711,13 +711,13 @@ float ddr3_get_device_size(u32 cs) * Small value will give wrong emem size in * ddr3_calc_mem_cs_size */ - return 0.01; + return 0; } } int ddr3_calc_mem_cs_size(u32 cs, u32 *cs_size) { - float cs_mem_size; + int cs_mem_size; /* Calculate in GiB */ cs_mem_size = ((ddr3_get_bus_width() / ddr3_get_device_width(cs)) * @@ -731,21 +731,12 @@ int ddr3_calc_mem_cs_size(u32 cs, u32 *cs_size) */ cs_mem_size *= DDR_CONTROLLER_BUS_WIDTH_MULTIPLIER; - if (cs_mem_size == 0.125) { - *cs_size = 128 << 20; - } else if (cs_mem_size == 0.25) { - *cs_size = 256 << 20; - } else if (cs_mem_size == 0.5) { - *cs_size = 512 << 20; - } else if (cs_mem_size == 1) { - *cs_size = 1 << 30; - } else if (cs_mem_size == 2) { - *cs_size = 2 << 30; - } else { + if (!cs_mem_size || (cs_mem_size == 64) || (cs_mem_size == 4096)) { DEBUG_INIT_C("Error: Wrong Memory size of Cs: ", cs, 1); return MV_BAD_VALUE; } + *cs_size = cs_mem_size << 20; return MV_OK; } From fbaf42724f372ee3fb0d7cd83107f5bae416028f Mon Sep 17 00:00:00 2001 From: Stefan Roese Date: Wed, 13 Apr 2016 11:02:20 +0200 Subject: [PATCH 105/162] arm: mvebu: theadorable: Enable CONFIG_ZERO_BOOTDELAY_CHECK Enable bootdelay 0 check so that booting can be interrupted even with bootdelay configured to 0. Signed-off-by: Stefan Roese --- include/configs/theadorable.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/configs/theadorable.h b/include/configs/theadorable.h index 1caa858856..dda70c5c81 100644 --- a/include/configs/theadorable.h +++ b/include/configs/theadorable.h @@ -64,6 +64,7 @@ #define PHY_ANEG_TIMEOUT 8000 /* PHY needs a longer aneg time */ #define CONFIG_SYS_CONSOLE_INFO_QUIET /* don't print console @ startup */ +#define CONFIG_ZERO_BOOTDELAY_CHECK /* check for keypress on bootdelay==0 */ #define CONFIG_SYS_ALT_MEMTEST #define CONFIG_PREBOOT From 2636ac65a84f2bbab4b6a773384cfc630b9b6d7b Mon Sep 17 00:00:00 2001 From: Nikita Kiryanov Date: Sat, 16 Apr 2016 17:55:02 +0300 Subject: [PATCH 106/162] cmd: eeprom: add bus switching support for all i2c drivers The i2c_init function is always provided when CONFIG_SYS_I2C is defined. No need to limit ourselves to just one supported I2C driver (soft_i2c). Update the #ifdef conditions to support bus switching for all I2C drivers. Cc: Heiko Schocher Cc: Marek Vasut Cc: Igor Grinberg Cc: Tom Rini Signed-off-by: Nikita Kiryanov --- cmd/eeprom.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/eeprom.c b/cmd/eeprom.c index e5457ba0cf..208b4138c1 100644 --- a/cmd/eeprom.c +++ b/cmd/eeprom.c @@ -72,7 +72,7 @@ void eeprom_init(int bus) #endif /* I2C EEPROM */ -#if defined(CONFIG_HARD_I2C) || defined(CONFIG_SYS_I2C_SOFT) +#if defined(CONFIG_HARD_I2C) || defined(CONFIG_SYS_I2C) #if defined(CONFIG_SYS_I2C) if (bus >= 0) i2c_set_bus_num(bus); From aa9e60441095ee3f20a109742e3ba5cdfd28458b Mon Sep 17 00:00:00 2001 From: Nikita Kiryanov Date: Sat, 16 Apr 2016 17:55:03 +0300 Subject: [PATCH 107/162] cmd: eeprom: add support for layout aware commands Introduce the (optional) eeprom print and eeprom update commands. These commands are eeprom layout aware: * The eeprom print command prints the contents of the eeprom in a human readable way (eeprom layout fields, and data formatted to be fit for human consumption). * The eeprom update command allows user to update eeprom fields by specifying the field name, and providing the new data in a human readable format (same format as displayed by the eeprom print command). * Both commands can either auto detect the layout, or be told which layout to use. New CONFIG options: CONFIG_CMD_EEPROM_LAYOUT - enables commands. CONFIG_EEPROM_LAYOUT_HELP_STRING - tells user what layout names are supported Feature API: __weak int parse_layout_version(char *str) - override to provide your own layout name parsing __weak void __eeprom_layout_assign(struct eeprom_layout *layout, int layout_version); - override to setup the layout metadata based on the version __weak int eeprom_layout_detect(unsigned char *data) - override to provide your own algorithm for detecting layout version eeprom_field.c - contains various printing and updating functions for common types of eeprom fields. Can be used for defining custom layouts. Cc: Heiko Schocher Cc: Marek Vasut Cc: Simon Glass Cc: Igor Grinberg Cc: Tom Rini Signed-off-by: Nikita Kiryanov --- README | 1 + cmd/eeprom.c | 148 +++++++++++++++++++- common/Makefile | 3 + common/eeprom/eeprom_field.c | 250 ++++++++++++++++++++++++++++++++++ common/eeprom/eeprom_layout.c | 125 +++++++++++++++++ include/eeprom_field.h | 39 ++++++ include/eeprom_layout.h | 33 +++++ 7 files changed, 598 insertions(+), 1 deletion(-) create mode 100644 common/eeprom/eeprom_field.c create mode 100644 common/eeprom/eeprom_layout.c create mode 100644 include/eeprom_field.h create mode 100644 include/eeprom_layout.h diff --git a/README b/README index 94e9943b04..6f4c09a3a1 100644 --- a/README +++ b/README @@ -1003,6 +1003,7 @@ The following options need to be configured: CONFIG_CMD_ECHO echo arguments CONFIG_CMD_EDITENV edit env variable CONFIG_CMD_EEPROM * EEPROM read/write support + CONFIG_CMD_EEPROM_LAYOUT* EEPROM layout aware commands CONFIG_CMD_ELF * bootelf, bootvx CONFIG_CMD_ENV_CALLBACK * display details about env callbacks CONFIG_CMD_ENV_FLAGS * display details about env flags diff --git a/cmd/eeprom.c b/cmd/eeprom.c index 208b4138c1..39ebee8dd9 100644 --- a/cmd/eeprom.c +++ b/cmd/eeprom.c @@ -207,6 +207,131 @@ int eeprom_write(unsigned dev_addr, unsigned offset, return ret; } +#ifdef CONFIG_CMD_EEPROM_LAYOUT +#include + +__weak int eeprom_parse_layout_version(char *str) +{ + return LAYOUT_VERSION_UNRECOGNIZED; +} + +static unsigned char eeprom_buf[CONFIG_SYS_EEPROM_SIZE]; + +#ifndef CONFIG_EEPROM_LAYOUT_HELP_STRING +#define CONFIG_EEPROM_LAYOUT_HELP_STRING "" +#endif + +enum eeprom_action { + EEPROM_PRINT, + EEPROM_UPDATE, + EEPROM_ACTION_INVALID, +}; + +static enum eeprom_action parse_action(char *cmd) +{ + if (!strncmp(cmd, "print", 5)) + return EEPROM_PRINT; + if (!strncmp(cmd, "update", 6)) + return EEPROM_UPDATE; + + return EEPROM_ACTION_INVALID; +} + +static int parse_numeric_param(char *str) +{ + char *endptr; + int value = simple_strtol(str, &endptr, 16); + + return (*endptr != '\0') ? -1 : value; +} + +static int eeprom_execute_command(enum eeprom_action action, int i2c_bus, + int i2c_addr, int layout_ver, char *key, + char *value) +{ + int rcode; + struct eeprom_layout layout; + + if (action == EEPROM_ACTION_INVALID) + return CMD_RET_USAGE; + + eeprom_init(i2c_bus); + rcode = eeprom_read(i2c_addr, 0, eeprom_buf, CONFIG_SYS_EEPROM_SIZE); + if (rcode < 0) + return rcode; + + eeprom_layout_setup(&layout, eeprom_buf, CONFIG_SYS_EEPROM_SIZE, + layout_ver); + + if (action == EEPROM_PRINT) { + layout.print(&layout); + return 0; + } + + layout.update(&layout, key, value); + + rcode = eeprom_write(i2c_addr, 0, layout.data, CONFIG_SYS_EEPROM_SIZE); + + return rcode; +} + +#define NEXT_PARAM(argc, index) { (argc)--; (index)++; } +static int do_eeprom_layout(cmd_tbl_t *cmdtp, int flag, int argc, + char * const argv[]) +{ + int layout_ver = LAYOUT_VERSION_AUTODETECT; + enum eeprom_action action = EEPROM_ACTION_INVALID; + int i2c_bus = -1, i2c_addr = -1, index = 0; + char *field_name = ""; + char *field_value = ""; + + if (argc <= 1) + return CMD_RET_USAGE; + + NEXT_PARAM(argc, index); /* Skip program name */ + + action = parse_action(argv[index]); + NEXT_PARAM(argc, index); + + if (argc <= 1) + return CMD_RET_USAGE; + + if (!strcmp(argv[index], "-l")) { + NEXT_PARAM(argc, index); + + layout_ver = eeprom_parse_layout_version(argv[index]); + NEXT_PARAM(argc, index); + } + + if (argc <= 1) + return CMD_RET_USAGE; + + i2c_bus = parse_numeric_param(argv[index]); + NEXT_PARAM(argc, index); + + i2c_addr = parse_numeric_param(argv[index]); + NEXT_PARAM(argc, index); + + if (action == EEPROM_PRINT) + goto done; + + if (argc) { + field_name = argv[index]; + NEXT_PARAM(argc, index); + } + + if (argc) { + field_value = argv[index]; + NEXT_PARAM(argc, index); + } + +done: + return eeprom_execute_command(action, i2c_bus, i2c_addr, layout_ver, + field_name, field_value); +} + +#endif + static int do_eeprom(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { const char *const fmt = @@ -216,6 +341,13 @@ static int do_eeprom(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) ulong dev_addr, addr, off, cnt; int bus_addr; +#ifdef CONFIG_CMD_EEPROM_LAYOUT + if (argc >= 2) { + if (!strcmp(argv[1], "update") || !strcmp(argv[1], "print")) + return do_eeprom_layout(cmdtp, flag, argc, argv); + } +#endif + switch (argc) { #ifdef CONFIG_SYS_DEF_EEPROM_ADDR case 5: @@ -261,9 +393,23 @@ static int do_eeprom(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) } U_BOOT_CMD( - eeprom, 7, 1, do_eeprom, + eeprom, 8, 1, do_eeprom, "EEPROM sub-system", "read addr off cnt\n" "eeprom write addr off cnt\n" " - read/write `cnt' bytes from `devaddr` EEPROM at offset `off'" +#ifdef CONFIG_CMD_EEPROM_LAYOUT + "\n" + "eeprom print [-l ] bus devaddr\n" + " - Print layout fields and their data in human readable format\n" + "eeprom update [-l ] bus devaddr \n" + " - Update a specific eeprom field with new data.\n" + " The new data must be written in the same human readable format as shown by the print command.\n" + "\n" + "LAYOUT VERSIONS\n" + "The -l option can be used to force the command to interpret the EEPROM data using the chosen layout.\n" + "If the -l option is omitted, the command will auto detect the layout based on the data in the EEPROM.\n" + "The values which can be provided with the -l option are:\n" + CONFIG_EEPROM_LAYOUT_HELP_STRING"\n" +#endif ) diff --git a/common/Makefile b/common/Makefile index f9b26b7bbe..0562d5cea4 100644 --- a/common/Makefile +++ b/common/Makefile @@ -156,6 +156,9 @@ obj-y += fb_nand.o endif endif +ifdef CONFIG_CMD_EEPROM_LAYOUT +obj-y += eeprom/eeprom_field.o eeprom/eeprom_layout.o +endif # We always have this since drivers/ddr/fs/interactive.c needs it obj-$(CONFIG_CMDLINE) += cli_simple.o diff --git a/common/eeprom/eeprom_field.c b/common/eeprom/eeprom_field.c new file mode 100644 index 0000000000..7f095a64a2 --- /dev/null +++ b/common/eeprom/eeprom_field.c @@ -0,0 +1,250 @@ +/* + * (C) Copyright 2009-2016 CompuLab, Ltd. + * + * Authors: Nikita Kiryanov + * Igor Grinberg + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include + +static void __eeprom_field_print_bin(const struct eeprom_field *field, + char *delimiter, bool reverse) +{ + int i; + int from = reverse ? field->size - 1 : 0; + int to = reverse ? 0 : field->size - 1; + + printf(PRINT_FIELD_SEGMENT, field->name); + for (i = from; i != to; reverse ? i-- : i++) + printf("%02x%s", field->buf[i], delimiter); + + printf("%02x\n", field->buf[i]); +} + +static int __eeprom_field_update_bin(struct eeprom_field *field, + const char *value, bool reverse) +{ + int len = strlen(value); + int k, j, i = reverse ? len - 1 : 0; + unsigned char byte; + char *endptr; + + /* each two characters in the string fit in one byte */ + if (len > field->size * 2) + return -1; + + memset(field->buf, 0, field->size); + + /* i - string iterator, j - buf iterator */ + for (j = 0; j < field->size; j++) { + byte = 0; + char tmp[3] = { 0, 0, 0 }; + + if ((reverse && i < 0) || (!reverse && i >= len)) + break; + + for (k = 0; k < 2; k++) { + if (reverse && i == 0) { + tmp[k] = value[i]; + break; + } + + tmp[k] = value[reverse ? i - 1 + k : i + k]; + } + + byte = simple_strtoul(tmp, &endptr, 0); + if (*endptr != '\0' || byte < 0) + return -1; + + field->buf[j] = byte; + i = reverse ? i - 2 : i + 2; + } + + return 0; +} + +static int __eeprom_field_update_bin_delim(struct eeprom_field *field, + char *value, char *delimiter) +{ + int count = 0; + int i, val; + const char *tmp = value; + char *tok; + char *endptr; + + tmp = strstr(tmp, delimiter); + while (tmp != NULL) { + count++; + tmp++; + tmp = strstr(tmp, delimiter); + } + + if (count > field->size) + return -1; + + tok = strtok(value, delimiter); + for (i = 0; tok && i < field->size; i++) { + val = simple_strtoul(tok, &endptr, 0); + if (*endptr != '\0') + return -1; + + /* here we assume that each tok is no more than byte long */ + field->buf[i] = (unsigned char)val; + tok = strtok(NULL, delimiter); + } + + return 0; +} + +/** + * eeprom_field_print_bin() - print a field which contains binary data + * + * Treat the field data as simple binary data, and print it as two digit + * hexadecimal values. + * Sample output: + * Field Name 0102030405060708090a + * + * @field: an initialized field to print + */ +void eeprom_field_print_bin(const struct eeprom_field *field) +{ + __eeprom_field_print_bin(field, "", false); +} + +/** + * eeprom_field_update_bin() - Update field with new data in binary form + * + * @field: an initialized field + * @value: a string of values (i.e. "10b234a") + */ +int eeprom_field_update_bin(struct eeprom_field *field, char *value) +{ + return __eeprom_field_update_bin(field, value, false); +} + +/** + * eeprom_field_update_reserved() - Update reserved field with new data in + * binary form + * + * @field: an initialized field + * @value: a space delimited string of byte values (i.e. "1 02 3 0x4") + */ +int eeprom_field_update_reserved(struct eeprom_field *field, char *value) +{ + return __eeprom_field_update_bin_delim(field, value, " "); +} + +/** + * eeprom_field_print_bin_rev() - print a field which contains binary data in + * reverse order + * + * Treat the field data as simple binary data, and print it in reverse order + * as two digit hexadecimal values. + * + * Data in field: + * 0102030405060708090a + * Sample output: + * Field Name 0a090807060504030201 + * + * @field: an initialized field to print + */ +void eeprom_field_print_bin_rev(const struct eeprom_field *field) +{ + __eeprom_field_print_bin(field, "", true); +} + +/** + * eeprom_field_update_bin_rev() - Update field with new data in binary form, + * storing it in reverse + * + * This function takes a string of byte values, and stores them + * in the field in the reverse order. i.e. if the input string was "1234", + * "3412" will be written to the field. + * + * @field: an initialized field + * @value: a string of byte values + */ +int eeprom_field_update_bin_rev(struct eeprom_field *field, char *value) +{ + return __eeprom_field_update_bin(field, value, true); +} + +/** + * eeprom_field_print_mac_addr() - print a field which contains a mac address + * + * Treat the field data as simple binary data, and print it formatted as a MAC + * address. + * Sample output: + * Field Name 01:02:03:04:05:06 + * + * @field: an initialized field to print + */ +void eeprom_field_print_mac(const struct eeprom_field *field) +{ + __eeprom_field_print_bin(field, ":", false); +} + +/** + * eeprom_field_update_mac() - Update a mac address field which contains binary + * data + * + * @field: an initialized field + * @value: a colon delimited string of byte values (i.e. "1:02:3:ff") + */ +int eeprom_field_update_mac(struct eeprom_field *field, char *value) +{ + return __eeprom_field_update_bin_delim(field, value, ":"); +} + +/** + * eeprom_field_print_ascii() - print a field which contains ASCII data + * @field: an initialized field to print + */ +void eeprom_field_print_ascii(const struct eeprom_field *field) +{ + char format[8]; + + sprintf(format, "%%.%ds\n", field->size); + printf(PRINT_FIELD_SEGMENT, field->name); + printf(format, field->buf); +} + +/** + * eeprom_field_update_ascii() - Update field with new data in ASCII form + * @field: an initialized field + * @value: the new string data + * + * Returns 0 on success, -1 of failure (new string too long). + */ +int eeprom_field_update_ascii(struct eeprom_field *field, char *value) +{ + if (strlen(value) >= field->size) { + printf("%s: new data too long\n", field->name); + return -1; + } + + strncpy((char *)field->buf, value, field->size - 1); + field->buf[field->size - 1] = '\0'; + + return 0; +} + +/** + * eeprom_field_print_reserved() - print the "Reserved fields" field + * + * Print a notice that the following field_size bytes are reserved. + * + * Sample output: + * Reserved fields (64 bytes) + * + * @field: an initialized field to print + */ +void eeprom_field_print_reserved(const struct eeprom_field *field) +{ + printf(PRINT_FIELD_SEGMENT, "Reserved fields\t"); + printf("(%d bytes)\n", field->size); +} diff --git a/common/eeprom/eeprom_layout.c b/common/eeprom/eeprom_layout.c new file mode 100644 index 0000000000..c05923328a --- /dev/null +++ b/common/eeprom/eeprom_layout.c @@ -0,0 +1,125 @@ +/* + * (C) Copyright 2009-2016 CompuLab, Ltd. + * + * Authors: Nikita Kiryanov + * Igor Grinberg + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include + +#define NO_LAYOUT_FIELDS "Unknown layout. Dumping raw data\n" + +struct eeprom_field layout_unknown[1] = { + { NO_LAYOUT_FIELDS, 256, NULL, eeprom_field_print_bin, + eeprom_field_update_bin }, +}; + +/* + * eeprom_layout_detect() - detect layout based on the contents of the data. + * @data: Pointer to the data to be analyzed. + * + * Returns: the detected layout version. + */ +__weak int eeprom_layout_detect(unsigned char *data) +{ + return LAYOUT_VERSION_UNRECOGNIZED; +} + +/* + * __eeprom_layout_assign() - set the layout fields + * @layout: A pointer to an existing struct layout. + * @layout_version: The version number of the desired layout + */ +__weak void __eeprom_layout_assign(struct eeprom_layout *layout, + int layout_version) +{ + layout->fields = layout_unknown; + layout->num_of_fields = ARRAY_SIZE(layout_unknown); +} +void eeprom_layout_assign(struct eeprom_layout *layout, int layout_version) \ + __attribute__((weak, alias("__eeprom_layout_assign"))); + +/* + * eeprom_layout_print() - print the layout and the data which is assigned to it + * @layout: A pointer to an existing struct layout. + */ +static void eeprom_layout_print(const struct eeprom_layout *layout) +{ + int i; + struct eeprom_field *fields = layout->fields; + + for (i = 0; i < layout->num_of_fields; i++) + fields[i].print(&fields[i]); +} + +/* + * eeprom_layout_update_field() - update a single field in the layout data. + * @layout: A pointer to an existing struct layout. + * @field_name: The name of the field to update. + * @new_data: The new field data (a string. Format depends on the field) + * + * Returns: 0 on success, negative error value on failure. + */ +static int eeprom_layout_update_field(struct eeprom_layout *layout, + char *field_name, char *new_data) +{ + int i, err; + struct eeprom_field *fields = layout->fields; + + if (new_data == NULL) + return 0; + + if (field_name == NULL) + return -1; + + for (i = 0; i < layout->num_of_fields; i++) { + if (fields[i].name == RESERVED_FIELDS || + strcmp(fields[i].name, field_name)) + continue; + + err = fields[i].update(&fields[i], new_data); + if (err) + printf("Invalid data for field %s\n", field_name); + + return err; + } + + printf("No such field '%s'\n", field_name); + + return -1; +} + +/* + * eeprom_layout_setup() - setup layout struct with the layout data and + * metadata as dictated by layout_version + * @layout: A pointer to an existing struct layout. + * @buf: A buffer initialized with the eeprom data. + * @buf_size: Size of buf in bytes. + * @layout version: The version number of the layout. + */ +void eeprom_layout_setup(struct eeprom_layout *layout, unsigned char *buf, + unsigned int buf_size, int layout_version) +{ + int i; + + if (layout_version == LAYOUT_VERSION_AUTODETECT) + layout->layout_version = eeprom_layout_detect(buf); + else + layout->layout_version = layout_version; + + eeprom_layout_assign(layout, layout_version); + layout->data = buf; + for (i = 0; i < layout->num_of_fields; i++) { + layout->fields[i].buf = buf; + buf += layout->fields[i].size; + } + + layout->data_size = buf_size; + layout->print = eeprom_layout_print; + layout->update = eeprom_layout_update_field; +} diff --git a/include/eeprom_field.h b/include/eeprom_field.h new file mode 100644 index 0000000000..94e259ff73 --- /dev/null +++ b/include/eeprom_field.h @@ -0,0 +1,39 @@ +/* + * (C) Copyright 2009-2016 CompuLab, Ltd. + * + * Authors: Nikita Kiryanov + * Igor Grinberg + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef _FIELD_ +#define _FIELD_ + +#define PRINT_FIELD_SEGMENT "%-30s" + +struct eeprom_field { + char *name; + int size; + unsigned char *buf; + + void (*print)(const struct eeprom_field *eeprom_field); + int (*update)(struct eeprom_field *eeprom_field, char *value); +}; + +void eeprom_field_print_bin(const struct eeprom_field *field); +int eeprom_field_update_bin(struct eeprom_field *field, char *value); + +void eeprom_field_print_bin_rev(const struct eeprom_field *field); +int eeprom_field_update_bin_rev(struct eeprom_field *field, char *value); + +void eeprom_field_print_mac(const struct eeprom_field *field); +int eeprom_field_update_mac(struct eeprom_field *field, char *value); + +void eeprom_field_print_ascii(const struct eeprom_field *field); +int eeprom_field_update_ascii(struct eeprom_field *field, char *value); + +void eeprom_field_print_reserved(const struct eeprom_field *field); +int eeprom_field_update_reserved(struct eeprom_field *field, char *value); + +#endif diff --git a/include/eeprom_layout.h b/include/eeprom_layout.h new file mode 100644 index 0000000000..459b99d861 --- /dev/null +++ b/include/eeprom_layout.h @@ -0,0 +1,33 @@ +/* + * (C) Copyright 2009-2016 CompuLab, Ltd. + * + * Authors: Nikita Kiryanov + * Igor Grinberg + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef _LAYOUT_ +#define _LAYOUT_ + +#define RESERVED_FIELDS NULL +#define LAYOUT_VERSION_UNRECOGNIZED -1 +#define LAYOUT_VERSION_AUTODETECT -2 + +struct eeprom_layout { + struct eeprom_field *fields; + int num_of_fields; + int layout_version; + unsigned char *data; + int data_size; + void (*print)(const struct eeprom_layout *eeprom_layout); + int (*update)(struct eeprom_layout *eeprom_layout, char *field_name, + char *new_data); +}; + +void eeprom_layout_setup(struct eeprom_layout *layout, unsigned char *buf, + unsigned int buf_size, int layout_version); +__weak void __eeprom_layout_assign(struct eeprom_layout *layout, + int layout_version); + +#endif From 8af5734b4e9322a9af8640ba1af48ebe14ebf6c3 Mon Sep 17 00:00:00 2001 From: Nikita Kiryanov Date: Sat, 16 Apr 2016 17:55:04 +0300 Subject: [PATCH 108/162] compulab: add support for layout aware eeprom commands Add layout definitions and implement functions for field printing/updating, layout detection, layout assignment, and layout parsing. Cc: Igor Grinberg Cc: Tom Rini Signed-off-by: Nikita Kiryanov --- board/compulab/common/eeprom.c | 344 +++++++++++++++++++++++++++++++++ 1 file changed, 344 insertions(+) diff --git a/board/compulab/common/eeprom.c b/board/compulab/common/eeprom.c index 630446820c..b5f1aa61cb 100644 --- a/board/compulab/common/eeprom.c +++ b/board/compulab/common/eeprom.c @@ -9,6 +9,9 @@ #include #include +#include +#include +#include #include "eeprom.h" #ifndef CONFIG_SYS_I2C_EEPROM_ADDR @@ -181,3 +184,344 @@ int cl_eeprom_get_product_name(uchar *buf, uint eeprom_bus) return err; } + +#ifdef CONFIG_CMD_EEPROM_LAYOUT +/** + * eeprom_field_print_bin_ver() - print a "version field" which contains binary + * data + * + * Treat the field data as simple binary data, and print it formatted as a + * version number (2 digits after decimal point). + * The field size must be exactly 2 bytes. + * + * Sample output: + * Field Name 123.45 + * + * @field: an initialized field to print + */ +void eeprom_field_print_bin_ver(const struct eeprom_field *field) +{ + if ((field->buf[0] == 0xff) && (field->buf[1] == 0xff)) { + field->buf[0] = 0; + field->buf[1] = 0; + } + + printf(PRINT_FIELD_SEGMENT, field->name); + int major = (field->buf[1] << 8 | field->buf[0]) / 100; + int minor = (field->buf[1] << 8 | field->buf[0]) - major * 100; + printf("%d.%02d\n", major, minor); +} + +/** + * eeprom_field_update_bin_ver() - update a "version field" which contains + * binary data + * + * This function takes a version string in the form of x.y (x and y are both + * decimal values, y is limited to two digits), translates it to the binary + * form, then writes it to the field. The field size must be exactly 2 bytes. + * + * This function strictly enforces the data syntax, and will not update the + * field if there's any deviation from it. It also protects from overflow. + * + * @field: an initialized field + * @value: a version string + * + * Returns 0 on success, -1 on failure. + */ +int eeprom_field_update_bin_ver(struct eeprom_field *field, char *value) +{ + char *endptr; + char *tok = strtok(value, "."); + if (tok == NULL) + return -1; + + int num = simple_strtol(tok, &endptr, 0); + if (*endptr != '\0') + return -1; + + tok = strtok(NULL, ""); + if (tok == NULL) + return -1; + + int remainder = simple_strtol(tok, &endptr, 0); + if (*endptr != '\0') + return -1; + + num = num * 100 + remainder; + if (num >> 16) + return -1; + + field->buf[0] = (unsigned char)num; + field->buf[1] = num >> 8; + + return 0; +} + +char *months[12] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; + +/** + * eeprom_field_print_date() - print a field which contains date data + * + * Treat the field data as simple binary data, and print it formatted as a date. + * Sample output: + * Field Name 07/Feb/2014 + * Field Name 56/BAD/9999 + * + * @field: an initialized field to print + */ +void eeprom_field_print_date(const struct eeprom_field *field) +{ + printf(PRINT_FIELD_SEGMENT, field->name); + printf("%02d/", field->buf[0]); + if (field->buf[1] >= 1 && field->buf[1] <= 12) + printf("%s", months[field->buf[1] - 1]); + else + printf("BAD"); + + printf("/%d\n", field->buf[3] << 8 | field->buf[2]); +} + +static int validate_date(unsigned char day, unsigned char month, + unsigned int year) +{ + int days_in_february; + + switch (month) { + case 0: + case 2: + case 4: + case 6: + case 7: + case 9: + case 11: + if (day > 31) + return -1; + break; + case 3: + case 5: + case 8: + case 10: + if (day > 30) + return -1; + break; + case 1: + days_in_february = 28; + if (year % 4 == 0) { + if (year % 100 != 0) + days_in_february = 29; + else if (year % 400 == 0) + days_in_february = 29; + } + + if (day > days_in_february) + return -1; + + break; + default: + return -1; + } + + return 0; +} + +/** + * eeprom_field_update_date() - update a date field which contains binary data + * + * This function takes a date string in the form of x/Mon/y (x and y are both + * decimal values), translates it to the binary representation, then writes it + * to the field. + * + * This function strictly enforces the data syntax, and will not update the + * field if there's any deviation from it. It also protects from overflow in the + * year value, and checks the validity of the date. + * + * @field: an initialized field + * @value: a date string + * + * Returns 0 on success, -1 on failure. + */ +int eeprom_field_update_date(struct eeprom_field *field, char *value) +{ + char *endptr; + char *tok1 = strtok(value, "/"); + char *tok2 = strtok(NULL, "/"); + char *tok3 = strtok(NULL, "/"); + + if (tok1 == NULL || tok2 == NULL || tok3 == NULL) { + printf("%s: syntax error\n", field->name); + return -1; + } + + unsigned char day = (unsigned char)simple_strtol(tok1, &endptr, 0); + if (*endptr != '\0' || day == 0) { + printf("%s: invalid day\n", field->name); + return -1; + } + + unsigned char month; + for (month = 1; month <= 12; month++) + if (!strcmp(tok2, months[month - 1])) + break; + + unsigned int year = simple_strtol(tok3, &endptr, 0); + if (*endptr != '\0') { + printf("%s: invalid year\n", field->name); + return -1; + } + + if (validate_date(day, month - 1, year)) { + printf("%s: invalid date\n", field->name); + return -1; + } + + if (year >> 16) { + printf("%s: year overflow\n", field->name); + return -1; + } + + field->buf[0] = day; + field->buf[1] = month; + field->buf[2] = (unsigned char)year; + field->buf[3] = (unsigned char)(year >> 8); + + return 0; +} + +#define LAYOUT_VERSION_LEGACY 1 +#define LAYOUT_VERSION_VER1 2 +#define LAYOUT_VERSION_VER2 3 +#define LAYOUT_VERSION_VER3 4 + +extern struct eeprom_field layout_unknown[1]; + +#define DEFINE_PRINT_UPDATE(x) eeprom_field_print_##x, eeprom_field_update_##x + +#ifdef CONFIG_CM_T3X +struct eeprom_field layout_legacy[5] = { + { "MAC address", 6, NULL, DEFINE_PRINT_UPDATE(mac) }, + { "Board Revision", 2, NULL, DEFINE_PRINT_UPDATE(bin) }, + { "Serial Number", 8, NULL, DEFINE_PRINT_UPDATE(bin) }, + { "Board Configuration", 64, NULL, DEFINE_PRINT_UPDATE(ascii) }, + { RESERVED_FIELDS, 176, NULL, eeprom_field_print_reserved, + eeprom_field_update_ascii }, +}; +#else +#define layout_legacy layout_unknown +#endif + +#if defined(CONFIG_CM_T3X) || defined(CONFIG_CM_T3517) +struct eeprom_field layout_v1[12] = { + { "Major Revision", 2, NULL, DEFINE_PRINT_UPDATE(bin_ver) }, + { "Minor Revision", 2, NULL, DEFINE_PRINT_UPDATE(bin_ver) }, + { "1st MAC Address", 6, NULL, DEFINE_PRINT_UPDATE(mac) }, + { "2nd MAC Address", 6, NULL, DEFINE_PRINT_UPDATE(mac) }, + { "Production Date", 4, NULL, DEFINE_PRINT_UPDATE(date) }, + { "Serial Number", 12, NULL, DEFINE_PRINT_UPDATE(bin_rev) }, + { RESERVED_FIELDS, 96, NULL, DEFINE_PRINT_UPDATE(reserved) }, + { "Product Name", 16, NULL, DEFINE_PRINT_UPDATE(ascii) }, + { "Product Options #1", 16, NULL, DEFINE_PRINT_UPDATE(ascii) }, + { "Product Options #2", 16, NULL, DEFINE_PRINT_UPDATE(ascii) }, + { "Product Options #3", 16, NULL, DEFINE_PRINT_UPDATE(ascii) }, + { RESERVED_FIELDS, 64, NULL, eeprom_field_print_reserved, + eeprom_field_update_ascii }, +}; +#else +#define layout_v1 layout_unknown +#endif + +struct eeprom_field layout_v2[15] = { + { "Major Revision", 2, NULL, DEFINE_PRINT_UPDATE(bin_ver) }, + { "Minor Revision", 2, NULL, DEFINE_PRINT_UPDATE(bin_ver) }, + { "1st MAC Address", 6, NULL, DEFINE_PRINT_UPDATE(mac) }, + { "2nd MAC Address", 6, NULL, DEFINE_PRINT_UPDATE(mac) }, + { "Production Date", 4, NULL, DEFINE_PRINT_UPDATE(date) }, + { "Serial Number", 12, NULL, DEFINE_PRINT_UPDATE(bin_rev) }, + { "3rd MAC Address (WIFI)", 6, NULL, DEFINE_PRINT_UPDATE(mac) }, + { "4th MAC Address (Bluetooth)", 6, NULL, DEFINE_PRINT_UPDATE(mac) }, + { "Layout Version", 1, NULL, DEFINE_PRINT_UPDATE(bin) }, + { RESERVED_FIELDS, 83, NULL, DEFINE_PRINT_UPDATE(reserved) }, + { "Product Name", 16, NULL, DEFINE_PRINT_UPDATE(ascii) }, + { "Product Options #1", 16, NULL, DEFINE_PRINT_UPDATE(ascii) }, + { "Product Options #2", 16, NULL, DEFINE_PRINT_UPDATE(ascii) }, + { "Product Options #3", 16, NULL, DEFINE_PRINT_UPDATE(ascii) }, + { RESERVED_FIELDS, 64, NULL, eeprom_field_print_reserved, + eeprom_field_update_ascii }, +}; + +struct eeprom_field layout_v3[16] = { + { "Major Revision", 2, NULL, DEFINE_PRINT_UPDATE(bin_ver) }, + { "Minor Revision", 2, NULL, DEFINE_PRINT_UPDATE(bin_ver) }, + { "1st MAC Address", 6, NULL, DEFINE_PRINT_UPDATE(mac) }, + { "2nd MAC Address", 6, NULL, DEFINE_PRINT_UPDATE(mac) }, + { "Production Date", 4, NULL, DEFINE_PRINT_UPDATE(date) }, + { "Serial Number", 12, NULL, DEFINE_PRINT_UPDATE(bin_rev) }, + { "3rd MAC Address (WIFI)", 6, NULL, DEFINE_PRINT_UPDATE(mac) }, + { "4th MAC Address (Bluetooth)", 6, NULL, DEFINE_PRINT_UPDATE(mac) }, + { "Layout Version", 1, NULL, DEFINE_PRINT_UPDATE(bin) }, + { "CompuLab EEPROM ID", 3, NULL, DEFINE_PRINT_UPDATE(bin) }, + { RESERVED_FIELDS, 80, NULL, DEFINE_PRINT_UPDATE(reserved) }, + { "Product Name", 16, NULL, DEFINE_PRINT_UPDATE(ascii) }, + { "Product Options #1", 16, NULL, DEFINE_PRINT_UPDATE(ascii) }, + { "Product Options #2", 16, NULL, DEFINE_PRINT_UPDATE(ascii) }, + { "Product Options #3", 16, NULL, DEFINE_PRINT_UPDATE(ascii) }, + { RESERVED_FIELDS, 64, NULL, eeprom_field_print_reserved, + eeprom_field_update_ascii }, +}; + +void eeprom_layout_assign(struct eeprom_layout *layout, int layout_version) +{ + switch (layout->layout_version) { + case LAYOUT_VERSION_LEGACY: + layout->fields = layout_legacy; + layout->num_of_fields = ARRAY_SIZE(layout_legacy); + break; + case LAYOUT_VERSION_VER1: + layout->fields = layout_v1; + layout->num_of_fields = ARRAY_SIZE(layout_v1); + break; + case LAYOUT_VERSION_VER2: + layout->fields = layout_v2; + layout->num_of_fields = ARRAY_SIZE(layout_v2); + break; + case LAYOUT_VERSION_VER3: + layout->fields = layout_v3; + layout->num_of_fields = ARRAY_SIZE(layout_v3); + break; + default: + __eeprom_layout_assign(layout, layout_version); + } +} + +int eeprom_parse_layout_version(char *str) +{ + if (!strcmp(str, "legacy")) + return LAYOUT_VERSION_LEGACY; + else if (!strcmp(str, "v1")) + return LAYOUT_VERSION_VER1; + else if (!strcmp(str, "v2")) + return LAYOUT_VERSION_VER2; + else if (!strcmp(str, "v3")) + return LAYOUT_VERSION_VER3; + else + return LAYOUT_VERSION_UNRECOGNIZED; +} + +int eeprom_layout_detect(unsigned char *data) +{ + switch (data[EEPROM_LAYOUT_VER_OFFSET]) { + case 0xff: + case 0: + return LAYOUT_VERSION_VER1; + case 2: + return LAYOUT_VERSION_VER2; + case 3: + return LAYOUT_VERSION_VER3; + } + + if (data[EEPROM_LAYOUT_VER_OFFSET] >= 0x20) + return LAYOUT_VERSION_LEGACY; + + return LAYOUT_VERSION_UNRECOGNIZED; +} +#endif From 126165312524305d1a5f2fc535e526fb92a3f8e0 Mon Sep 17 00:00:00 2001 From: Nikita Kiryanov Date: Sat, 16 Apr 2016 17:55:05 +0300 Subject: [PATCH 109/162] arm: cm-fx6: add support for eeprom layout comands Add support for EEPROM and EEPROM layout commands for CM-FX6. Cc: Igor Grinberg Cc: Tom Rini Signed-off-by: Nikita Kiryanov --- include/configs/cm_fx6.h | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/include/configs/cm_fx6.h b/include/configs/cm_fx6.h index 9a125529c6..1f20ec3c6d 100644 --- a/include/configs/cm_fx6.h +++ b/include/configs/cm_fx6.h @@ -255,4 +255,15 @@ #define CONFIG_VIDEO_LOGO #define CONFIG_VIDEO_BMP_LOGO +/* EEPROM */ +#define CONFIG_CMD_EEPROM +#define CONFIG_ENV_EEPROM_IS_ON_I2C +#define CONFIG_SYS_I2C_EEPROM_ADDR_LEN 1 +#define CONFIG_SYS_EEPROM_PAGE_WRITE_BITS 4 +#define CONFIG_SYS_EEPROM_PAGE_WRITE_DELAY_MS 5 +#define CONFIG_SYS_EEPROM_SIZE 256 + +#define CONFIG_CMD_EEPROM_LAYOUT +#define CONFIG_EEPROM_LAYOUT_HELP_STRING "v2, v3" + #endif /* __CONFIG_CM_FX6_H */ From 0e656b825e76a9ac583c60c5110f9723d9a9f5d1 Mon Sep 17 00:00:00 2001 From: Nikita Kiryanov Date: Sat, 16 Apr 2016 17:55:06 +0300 Subject: [PATCH 110/162] arm: cm-t335: add support for eeprom layout comands Add support for EEPROM and EEPROM layout commands for CM-T335. Cc: Igor Grinberg Cc: Tom Rini Signed-off-by: Nikita Kiryanov --- include/configs/cm_t335.h | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/include/configs/cm_t335.h b/include/configs/cm_t335.h index c4f1d4f438..6dbc9e980c 100644 --- a/include/configs/cm_t335.h +++ b/include/configs/cm_t335.h @@ -165,6 +165,17 @@ #define STATUS_LED_PERIOD (CONFIG_SYS_HZ / 2) #define STATUS_LED_BOOT 0 +/* EEPROM */ +#define CONFIG_CMD_EEPROM +#define CONFIG_ENV_EEPROM_IS_ON_I2C +#define CONFIG_SYS_I2C_EEPROM_ADDR_LEN 1 +#define CONFIG_SYS_EEPROM_PAGE_WRITE_BITS 4 +#define CONFIG_SYS_EEPROM_PAGE_WRITE_DELAY_MS 5 +#define CONFIG_SYS_EEPROM_SIZE 256 + +#define CONFIG_CMD_EEPROM_LAYOUT +#define CONFIG_EEPROM_LAYOUT_HELP_STRING "v2, v3" + #ifndef CONFIG_SPL_BUILD /* * Enable PCA9555 at I2C0-0x26. From 66b7e4201d90ed06ce10b7dff488c5e8932c38b2 Mon Sep 17 00:00:00 2001 From: Nikita Kiryanov Date: Sat, 16 Apr 2016 17:55:07 +0300 Subject: [PATCH 111/162] arm: cm-t54: add support for eeprom layout comands Add support for EEPROM and EEPROM layout commands for CM-T54. Cc: Igor Grinberg Cc: Tom Rini Signed-off-by: Nikita Kiryanov --- include/configs/cm_t54.h | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/include/configs/cm_t54.h b/include/configs/cm_t54.h index ac6103c066..ff63d7a775 100644 --- a/include/configs/cm_t54.h +++ b/include/configs/cm_t54.h @@ -81,6 +81,17 @@ /* Enabled commands */ +/* EEPROM */ +#define CONFIG_CMD_EEPROM +#define CONFIG_ENV_EEPROM_IS_ON_I2C +#define CONFIG_SYS_I2C_EEPROM_ADDR_LEN 1 +#define CONFIG_SYS_EEPROM_PAGE_WRITE_BITS 4 +#define CONFIG_SYS_EEPROM_PAGE_WRITE_DELAY_MS 5 +#define CONFIG_SYS_EEPROM_SIZE 256 + +#define CONFIG_CMD_EEPROM_LAYOUT +#define CONFIG_EEPROM_LAYOUT_HELP_STRING "v2, v3" + /* USB Networking options */ #define CONFIG_USB_HOST_ETHER #define CONFIG_USB_ETHER_SMSC95XX From 19a90ed67390f230373b736d328f5ca482f0f779 Mon Sep 17 00:00:00 2001 From: Nikita Kiryanov Date: Sat, 16 Apr 2016 17:55:08 +0300 Subject: [PATCH 112/162] arm: cm-t3517: add support for eeprom layout comands Add support for EEPROM and EEPROM layout commands for CM-T3517. Cc: Igor Grinberg Cc: Tom Rini Signed-off-by: Nikita Kiryanov --- include/configs/cm_t3517.h | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/include/configs/cm_t3517.h b/include/configs/cm_t3517.h index 7cedb6736d..7c087c6f5d 100644 --- a/include/configs/cm_t3517.h +++ b/include/configs/cm_t3517.h @@ -305,4 +305,15 @@ #define CONFIG_OMAP3_SPI +/* EEPROM */ +#define CONFIG_CMD_EEPROM +#define CONFIG_ENV_EEPROM_IS_ON_I2C +#define CONFIG_SYS_I2C_EEPROM_ADDR_LEN 1 +#define CONFIG_SYS_EEPROM_PAGE_WRITE_BITS 4 +#define CONFIG_SYS_EEPROM_PAGE_WRITE_DELAY_MS 5 +#define CONFIG_SYS_EEPROM_SIZE 256 + +#define CONFIG_CMD_EEPROM_LAYOUT +#define CONFIG_EEPROM_LAYOUT_HELP_STRING "v1, v2, v3" + #endif /* __CONFIG_H */ From bcb447e157edd50106a7995f7a4045a0b63914c7 Mon Sep 17 00:00:00 2001 From: Nikita Kiryanov Date: Sat, 16 Apr 2016 17:55:09 +0300 Subject: [PATCH 113/162] arm: cm-t35: add support for eeprom layout comands Add support for EEPROM and EEPROM layout commands for CM-T35. Cc: Igor Grinberg Cc: Tom Rini Signed-off-by: Nikita Kiryanov --- include/configs/cm_t35.h | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/include/configs/cm_t35.h b/include/configs/cm_t35.h index 5d581162cb..0fb853002c 100644 --- a/include/configs/cm_t35.h +++ b/include/configs/cm_t35.h @@ -361,4 +361,15 @@ #define CONFIG_SYS_SPL_MALLOC_START 0x80208000 #define CONFIG_SYS_SPL_MALLOC_SIZE 0x100000 +/* EEPROM */ +#define CONFIG_CMD_EEPROM +#define CONFIG_ENV_EEPROM_IS_ON_I2C +#define CONFIG_SYS_I2C_EEPROM_ADDR_LEN 1 +#define CONFIG_SYS_EEPROM_PAGE_WRITE_BITS 4 +#define CONFIG_SYS_EEPROM_PAGE_WRITE_DELAY_MS 5 +#define CONFIG_SYS_EEPROM_SIZE 256 + +#define CONFIG_CMD_EEPROM_LAYOUT +#define CONFIG_EEPROM_LAYOUT_HELP_STRING "legacy, v1, v2, v3" + #endif /* __CONFIG_H */ From 2d9a76b614c33e660b5556b5f96bd5ee4810953e Mon Sep 17 00:00:00 2001 From: Nikita Kiryanov Date: Sat, 16 Apr 2016 17:55:10 +0300 Subject: [PATCH 114/162] arm: cm-t43: add support for eeprom layout comands Add support for EEPROM and EEPROM layout commands for CM-T43. Cc: Igor Grinberg Cc: Tom Rini Signed-off-by: Nikita Kiryanov --- include/configs/cm_t43.h | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/include/configs/cm_t43.h b/include/configs/cm_t43.h index ee818ede26..c2dbd31803 100644 --- a/include/configs/cm_t43.h +++ b/include/configs/cm_t43.h @@ -170,4 +170,15 @@ #define CONFIG_SPL_I2C_SUPPORT #define CONFIG_SPL_POWER_SUPPORT +/* EEPROM */ +#define CONFIG_CMD_EEPROM +#define CONFIG_ENV_EEPROM_IS_ON_I2C +#define CONFIG_SYS_I2C_EEPROM_ADDR_LEN 1 +#define CONFIG_SYS_EEPROM_PAGE_WRITE_BITS 4 +#define CONFIG_SYS_EEPROM_PAGE_WRITE_DELAY_MS 5 +#define CONFIG_SYS_EEPROM_SIZE 256 + +#define CONFIG_CMD_EEPROM_LAYOUT +#define CONFIG_EEPROM_LAYOUT_HELP_STRING "v2, v3" + #endif /* __CONFIG_CM_T43_H */ From c40f03723fba2f77bccd92dd87fcd48c37d13cdc Mon Sep 17 00:00:00 2001 From: Nikita Kiryanov Date: Sat, 16 Apr 2016 17:55:11 +0300 Subject: [PATCH 115/162] eeprom: refactor i2c bus and devaddr parsing Introduce parse_i2c_bus_addr() to generalize the parsing of i2c bus number and i2c device address. This is done in preparation for merging layout aware and layout unaware command parsing into one function. No functional changes. Cc: Heiko Schocher Cc: Marek Vasut Cc: Simon Glass Cc: Igor Grinberg Cc: Tom Rini Signed-off-by: Nikita Kiryanov --- cmd/eeprom.c | 79 +++++++++++++++++++++++++++++++++++----------------- 1 file changed, 53 insertions(+), 26 deletions(-) diff --git a/cmd/eeprom.c b/cmd/eeprom.c index 39ebee8dd9..54bf06ceb3 100644 --- a/cmd/eeprom.c +++ b/cmd/eeprom.c @@ -207,6 +207,56 @@ int eeprom_write(unsigned dev_addr, unsigned offset, return ret; } +static int parse_numeric_param(char *str) +{ + char *endptr; + int value = simple_strtol(str, &endptr, 16); + + return (*endptr != '\0') ? -1 : value; +} + +/** + * parse_i2c_bus_addr - parse the i2c bus and i2c devaddr parameters + * + * @i2c_bus: address to store the i2c bus + * @i2c_addr: address to store the device i2c address + * @argc: count of command line arguments left to parse + * @argv: command line arguments left to parse + * @argc_no_bus_addr: argc value we expect to see when bus & addr aren't given + * + * @returns: number of arguments parsed or CMD_RET_USAGE if error + */ +static int parse_i2c_bus_addr(int *i2c_bus, ulong *i2c_addr, int argc, + char * const argv[], int argc_no_bus_addr) +{ + int argc_no_bus = argc_no_bus_addr + 1; + int argc_bus_addr = argc_no_bus_addr + 2; + +#ifdef CONFIG_SYS_DEF_EEPROM_ADDR + if (argc == argc_no_bus_addr) { + *i2c_bus = -1; + *i2c_addr = CONFIG_SYS_DEF_EEPROM_ADDR; + + return 0; + } +#endif + if (argc == argc_no_bus) { + *i2c_bus = -1; + *i2c_addr = parse_numeric_param(argv[0]); + + return 1; + } + + if (argc == argc_bus_addr) { + *i2c_bus = parse_numeric_param(argv[0]); + *i2c_addr = parse_numeric_param(argv[1]); + + return 2; + } + + return CMD_RET_USAGE; +} + #ifdef CONFIG_CMD_EEPROM_LAYOUT #include @@ -237,14 +287,6 @@ static enum eeprom_action parse_action(char *cmd) return EEPROM_ACTION_INVALID; } -static int parse_numeric_param(char *str) -{ - char *endptr; - int value = simple_strtol(str, &endptr, 16); - - return (*endptr != '\0') ? -1 : value; -} - static int eeprom_execute_command(enum eeprom_action action, int i2c_bus, int i2c_addr, int layout_ver, char *key, char *value) @@ -348,24 +390,9 @@ static int do_eeprom(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) } #endif - switch (argc) { -#ifdef CONFIG_SYS_DEF_EEPROM_ADDR - case 5: - bus_addr = -1; - dev_addr = CONFIG_SYS_DEF_EEPROM_ADDR; - break; -#endif - case 6: - bus_addr = -1; - dev_addr = simple_strtoul(*args++, NULL, 16); - break; - case 7: - bus_addr = simple_strtoul(*args++, NULL, 16); - dev_addr = simple_strtoul(*args++, NULL, 16); - break; - default: - return CMD_RET_USAGE; - } + rcode = parse_i2c_bus_addr(&bus_addr, &dev_addr, argc - 2, argv + 2, 3); + if (rcode == CMD_RET_USAGE) + return rcode; addr = simple_strtoul(*args++, NULL, 16); off = simple_strtoul(*args++, NULL, 16); From d92ea983b9dfc99063373c167dae6b7705bc552b Mon Sep 17 00:00:00 2001 From: Stanislav Galabov Date: Wed, 17 Feb 2016 15:23:29 +0200 Subject: [PATCH 116/162] Properly calculate ATA_SECTORWORDS, using a fixed-size integer, so it works for both 32-bit and 64-bit targets Signed-off-by: Stanislav Galabov --- include/ata.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/ata.h b/include/ata.h index 9d6f59c97b..dde377c99e 100644 --- a/include/ata.h +++ b/include/ata.h @@ -126,7 +126,7 @@ #define ATA_BLOCKSIZE 512 /* bytes */ #define ATA_BLOCKSHIFT 9 /* 2 ^ ATA_BLOCKSIZESHIFT = 512 */ -#define ATA_SECTORWORDS (512 / sizeof(unsigned long)) +#define ATA_SECTORWORDS (512 / sizeof(uint32_t)) #ifndef ATA_RESET_TIME #define ATA_RESET_TIME 60 /* spec allows up to 31 seconds */ From 713a9e15bba4a5b6582d5e85fef2f282782cbed7 Mon Sep 17 00:00:00 2001 From: Stanislav Galabov Date: Wed, 17 Feb 2016 15:23:30 +0200 Subject: [PATCH 117/162] Use CONFIG_IDE_SWAP_IO when running on big-endian MIPS (32 or 64-bit) in QEMU so that IDE transfers work properly Signed-off-by: Stanislav Galabov --- include/configs/qemu-mips.h | 4 ++++ include/configs/qemu-mips64.h | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/include/configs/qemu-mips.h b/include/configs/qemu-mips.h index a7cd00350d..702967c4e8 100644 --- a/include/configs/qemu-mips.h +++ b/include/configs/qemu-mips.h @@ -58,6 +58,10 @@ #define CONFIG_CMD_IDE #define CONFIG_DOS_PARTITION +#ifdef CONFIG_SYS_BIG_ENDIAN +#define CONFIG_IDE_SWAP_IO +#endif + #define CONFIG_SYS_IDE_MAXBUS 2 #define CONFIG_SYS_ATA_IDE0_OFFSET 0x1f0 #define CONFIG_SYS_ATA_IDE1_OFFSET 0x170 diff --git a/include/configs/qemu-mips64.h b/include/configs/qemu-mips64.h index 394382c458..239454984a 100644 --- a/include/configs/qemu-mips64.h +++ b/include/configs/qemu-mips64.h @@ -58,6 +58,10 @@ #define CONFIG_CMD_IDE #define CONFIG_DOS_PARTITION +#ifdef CONFIG_SYS_BIG_ENDIAN +#define CONFIG_IDE_SWAP_IO +#endif + #define CONFIG_SYS_IDE_MAXBUS 2 #define CONFIG_SYS_ATA_IDE0_OFFSET 0x1f0 #define CONFIG_SYS_ATA_IDE1_OFFSET 0x170 From 78757d52c8b27f7f33ab4035706796a414c81128 Mon Sep 17 00:00:00 2001 From: Stanislav Galabov Date: Wed, 17 Feb 2016 15:23:31 +0200 Subject: [PATCH 118/162] Fix FreeBSD loader API so that it works on both 32-bit and 64-bit targets. Specifically tested on MIPS under QEMU (works with all combination of bit-ness and endian-ness) Signed-off-by: Stanislav Galabov --- api/api.c | 58 +++++++++++++++++++++---------------------- examples/api/Makefile | 4 +++ examples/api/crt0.S | 13 +++++----- examples/api/glue.c | 18 +++++++------- 4 files changed, 49 insertions(+), 44 deletions(-) diff --git a/api/api.c b/api/api.c index 457dc36f6f..8a1433af78 100644 --- a/api/api.c +++ b/api/api.c @@ -52,7 +52,7 @@ static int API_getc(va_list ap) { int *c; - if ((c = (int *)va_arg(ap, u_int32_t)) == NULL) + if ((c = (int *)va_arg(ap, uintptr_t)) == NULL) return API_EINVAL; *c = getc(); @@ -68,7 +68,7 @@ static int API_tstc(va_list ap) { int *t; - if ((t = (int *)va_arg(ap, u_int32_t)) == NULL) + if ((t = (int *)va_arg(ap, uintptr_t)) == NULL) return API_EINVAL; *t = tstc(); @@ -84,7 +84,7 @@ static int API_putc(va_list ap) { char *c; - if ((c = (char *)va_arg(ap, u_int32_t)) == NULL) + if ((c = (char *)va_arg(ap, uintptr_t)) == NULL) return API_EINVAL; putc(*c); @@ -100,7 +100,7 @@ static int API_puts(va_list ap) { char *s; - if ((s = (char *)va_arg(ap, u_int32_t)) == NULL) + if ((s = (char *)va_arg(ap, uintptr_t)) == NULL) return API_EINVAL; puts(s); @@ -132,7 +132,7 @@ static int API_get_sys_info(va_list ap) { struct sys_info *si; - si = (struct sys_info *)va_arg(ap, u_int32_t); + si = (struct sys_info *)va_arg(ap, uintptr_t); if (si == NULL) return API_ENOMEM; @@ -148,7 +148,7 @@ static int API_udelay(va_list ap) { unsigned long *d; - if ((d = (unsigned long *)va_arg(ap, u_int32_t)) == NULL) + if ((d = (unsigned long *)va_arg(ap, unsigned long)) == NULL) return API_EINVAL; udelay(*d); @@ -164,11 +164,11 @@ static int API_get_timer(va_list ap) { unsigned long *base, *cur; - cur = (unsigned long *)va_arg(ap, u_int32_t); + cur = (unsigned long *)va_arg(ap, unsigned long); if (cur == NULL) return API_EINVAL; - base = (unsigned long *)va_arg(ap, u_int32_t); + base = (unsigned long *)va_arg(ap, unsigned long); if (base == NULL) return API_EINVAL; @@ -199,7 +199,7 @@ static int API_dev_enum(va_list ap) struct device_info *di; /* arg is ptr to the device_info struct we are going to fill out */ - di = (struct device_info *)va_arg(ap, u_int32_t); + di = (struct device_info *)va_arg(ap, uintptr_t); if (di == NULL) return API_EINVAL; @@ -233,7 +233,7 @@ static int API_dev_open(va_list ap) int err = 0; /* arg is ptr to the device_info struct */ - di = (struct device_info *)va_arg(ap, u_int32_t); + di = (struct device_info *)va_arg(ap, uintptr_t); if (di == NULL) return API_EINVAL; @@ -265,7 +265,7 @@ static int API_dev_close(va_list ap) int err = 0; /* arg is ptr to the device_info struct */ - di = (struct device_info *)va_arg(ap, u_int32_t); + di = (struct device_info *)va_arg(ap, uintptr_t); if (di == NULL) return API_EINVAL; @@ -319,7 +319,7 @@ static int API_dev_write(va_list ap) int err = 0; /* 1. arg is ptr to the device_info struct */ - di = (struct device_info *)va_arg(ap, u_int32_t); + di = (struct device_info *)va_arg(ap, uintptr_t); if (di == NULL) return API_EINVAL; @@ -329,12 +329,12 @@ static int API_dev_write(va_list ap) return API_ENODEV; /* 2. arg is ptr to buffer from where to get data to write */ - buf = (void *)va_arg(ap, u_int32_t); + buf = (void *)va_arg(ap, uintptr_t); if (buf == NULL) return API_EINVAL; /* 3. arg is length of buffer */ - len = (int *)va_arg(ap, u_int32_t); + len = (int *)va_arg(ap, uintptr_t); if (len == NULL) return API_EINVAL; if (*len <= 0) @@ -387,7 +387,7 @@ static int API_dev_read(va_list ap) int *len_net, *act_len_net; /* 1. arg is ptr to the device_info struct */ - di = (struct device_info *)va_arg(ap, u_int32_t); + di = (struct device_info *)va_arg(ap, uintptr_t); if (di == NULL) return API_EINVAL; @@ -397,23 +397,23 @@ static int API_dev_read(va_list ap) return API_ENODEV; /* 2. arg is ptr to buffer from where to put the read data */ - buf = (void *)va_arg(ap, u_int32_t); + buf = (void *)va_arg(ap, uintptr_t); if (buf == NULL) return API_EINVAL; if (di->type & DEV_TYP_STOR) { /* 3. arg - ptr to var with # of blocks to read */ - len_stor = (lbasize_t *)va_arg(ap, u_int32_t); + len_stor = (lbasize_t *)va_arg(ap, uintptr_t); if (!len_stor) return API_EINVAL; if (*len_stor <= 0) return API_EINVAL; /* 4. arg - ptr to var with start block */ - start = (lbastart_t *)va_arg(ap, u_int32_t); + start = (lbastart_t *)va_arg(ap, uintptr_t); /* 5. arg - ptr to var where to put the len actually read */ - act_len_stor = (lbasize_t *)va_arg(ap, u_int32_t); + act_len_stor = (lbasize_t *)va_arg(ap, uintptr_t); if (!act_len_stor) return API_EINVAL; @@ -422,14 +422,14 @@ static int API_dev_read(va_list ap) } else if (di->type & DEV_TYP_NET) { /* 3. arg points to the var with length of packet to read */ - len_net = (int *)va_arg(ap, u_int32_t); + len_net = (int *)va_arg(ap, uintptr_t); if (!len_net) return API_EINVAL; if (*len_net <= 0) return API_EINVAL; /* 4. - ptr to var where to put the len actually read */ - act_len_net = (int *)va_arg(ap, u_int32_t); + act_len_net = (int *)va_arg(ap, uintptr_t); if (!act_len_net) return API_EINVAL; @@ -453,9 +453,9 @@ static int API_env_get(va_list ap) { char *name, **value; - if ((name = (char *)va_arg(ap, u_int32_t)) == NULL) + if ((name = (char *)va_arg(ap, uintptr_t)) == NULL) return API_EINVAL; - if ((value = (char **)va_arg(ap, u_int32_t)) == NULL) + if ((value = (char **)va_arg(ap, uintptr_t)) == NULL) return API_EINVAL; *value = getenv(name); @@ -476,9 +476,9 @@ static int API_env_set(va_list ap) { char *name, *value; - if ((name = (char *)va_arg(ap, u_int32_t)) == NULL) + if ((name = (char *)va_arg(ap, uintptr_t)) == NULL) return API_EINVAL; - if ((value = (char *)va_arg(ap, u_int32_t)) == NULL) + if ((value = (char *)va_arg(ap, uintptr_t)) == NULL) return API_EINVAL; setenv(name, value); @@ -498,9 +498,9 @@ static int API_env_enum(va_list ap) int i, n; char *last, **next; - last = (char *)va_arg(ap, u_int32_t); + last = (char *)va_arg(ap, unsigned long); - if ((next = (char **)va_arg(ap, u_int32_t)) == NULL) + if ((next = (char **)va_arg(ap, uintptr_t)) == NULL) return API_EINVAL; if (last == NULL) @@ -662,14 +662,14 @@ void api_init(void) } setenv_hex("api_address", (unsigned long)sig); - debugf("API sig @ 0x%08x\n", sig); + debugf("API sig @ 0x%lX\n", (unsigned long)sig); memcpy(sig->magic, API_SIG_MAGIC, 8); sig->version = API_SIG_VERSION; sig->syscall = &syscall; sig->checksum = 0; sig->checksum = crc32(0, (unsigned char *)sig, sizeof(struct api_signature)); - debugf("syscall entry: 0x%08x\n", sig->syscall); + debugf("syscall entry: 0x%lX\n", (unsigned long)sig->syscall); } void platform_set_mr(struct sys_info *si, unsigned long start, unsigned long size, diff --git a/examples/api/Makefile b/examples/api/Makefile index 4e9b8ea17d..6cffee7465 100644 --- a/examples/api/Makefile +++ b/examples/api/Makefile @@ -11,8 +11,12 @@ ifeq ($(ARCH),arm) LOAD_ADDR = 0x1000000 endif ifeq ($(ARCH),mips) +ifdef CONFIG_64BIT +LOAD_ADDR = 0xffffffff80200000 +else LOAD_ADDR = 0x80200000 endif +endif # Resulting ELF and binary exectuables will be named demo and demo.bin extra-y = demo diff --git a/examples/api/crt0.S b/examples/api/crt0.S index ced2c82e5f..5a7049d6b4 100644 --- a/examples/api/crt0.S +++ b/examples/api/crt0.S @@ -41,28 +41,29 @@ syscall: ldr pc, [ip] #elif defined(CONFIG_MIPS) +#include .text .globl __start .ent __start __start: - sw $sp, search_hint + PTR_S $sp, search_hint b main .end __start .globl syscall .ent syscall syscall: - sw $ra, return_addr - lw $t9, syscall_ptr + PTR_S $ra, return_addr + PTR_L $t9, syscall_ptr jalr $t9 nop - lw $ra, return_addr + PTR_L $ra, return_addr jr $ra nop .end syscall return_addr: - .align 4 + .align 8 .long 0 #else #error No support for this arch! @@ -70,7 +71,7 @@ return_addr: .globl syscall_ptr syscall_ptr: - .align 4 + .align 8 .long 0 .globl search_hint diff --git a/examples/api/glue.c b/examples/api/glue.c index d619518d42..8aabf32c89 100644 --- a/examples/api/glue.c +++ b/examples/api/glue.c @@ -77,7 +77,7 @@ int ub_getc(void) { int c; - if (!syscall(API_GETC, NULL, (uint32_t)&c)) + if (!syscall(API_GETC, NULL, &c)) return -1; return c; @@ -87,7 +87,7 @@ int ub_tstc(void) { int t; - if (!syscall(API_TSTC, NULL, (uint32_t)&t)) + if (!syscall(API_TSTC, NULL, &t)) return -1; return t; @@ -95,12 +95,12 @@ int ub_tstc(void) void ub_putc(char c) { - syscall(API_PUTC, NULL, (uint32_t)&c); + syscall(API_PUTC, NULL, &c); } void ub_puts(const char *s) { - syscall(API_PUTS, NULL, (uint32_t)s); + syscall(API_PUTS, NULL, s); } /**************************************** @@ -126,7 +126,7 @@ struct sys_info * ub_get_sys_info(void) si.mr_no = UB_MAX_MR; memset(&mr, 0, sizeof(mr)); - if (!syscall(API_GET_SYS_INFO, &err, (u_int32_t)&si)) + if (!syscall(API_GET_SYS_INFO, &err, &si)) return NULL; return ((err) ? NULL : &si); @@ -344,7 +344,7 @@ char * ub_env_get(const char *name) { char *value; - if (!syscall(API_ENV_GET, NULL, (uint32_t)name, (uint32_t)&value)) + if (!syscall(API_ENV_GET, NULL, name, &value)) return NULL; return value; @@ -352,7 +352,7 @@ char * ub_env_get(const char *name) void ub_env_set(const char *name, char *value) { - syscall(API_ENV_SET, NULL, (uint32_t)name, (uint32_t)value); + syscall(API_ENV_SET, NULL, name, value); } static char env_name[256]; @@ -369,7 +369,7 @@ const char * ub_env_enum(const char *last) * 'name=val' string), since the API_ENUM_ENV call uses envmatch() * internally, which handles such case */ - if (!syscall(API_ENV_ENUM, NULL, (uint32_t)last, (uint32_t)&env)) + if (!syscall(API_ENV_ENUM, NULL, last, &env)) return NULL; if (!env) @@ -396,7 +396,7 @@ int ub_display_get_info(int type, struct display_info *di) { int err = 0; - if (!syscall(API_DISPLAY_GET_INFO, &err, (uint32_t)type, (uint32_t)di)) + if (!syscall(API_DISPLAY_GET_INFO, &err, type, di)) return API_ESYSC; return err; From 4a48cfc4e57b4b247d94a614b2fbfcf03aa45ea1 Mon Sep 17 00:00:00 2001 From: Stanislav Galabov Date: Wed, 17 Feb 2016 15:23:33 +0200 Subject: [PATCH 119/162] Add support for 64-bit MIPS to examples/standalone Signed-off-by: Stanislav Galabov --- examples/standalone/stubs.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/examples/standalone/stubs.c b/examples/standalone/stubs.c index 920a0a9cf3..0d62067e03 100644 --- a/examples/standalone/stubs.c +++ b/examples/standalone/stubs.c @@ -65,6 +65,23 @@ gd_t *global_data; : : "i"(offsetof(gd_t, jt)), "i"(FO(x)) : "ip"); #endif #elif defined(CONFIG_MIPS) +#ifdef CONFIG_CPU_MIPS64 +/* + * k0 ($26) holds the pointer to the global_data; t9 ($25) is a call- + * clobbered register that is also used to set gp ($26). Note that the + * jr instruction also executes the instruction immediately following + * it; however, GCC/mips generates an additional `nop' after each asm + * statement + */ +#define EXPORT_FUNC(f, a, x, ...) \ + asm volatile ( \ +" .globl " #x "\n" \ +#x ":\n" \ +" ld $25, %0($26)\n" \ +" ld $25, %1($25)\n" \ +" jr $25\n" \ + : : "i"(offsetof(gd_t, jt)), "i"(FO(x)) : "t9"); +#else /* * k0 ($26) holds the pointer to the global_data; t9 ($25) is a call- * clobbered register that is also used to set gp ($26). Note that the @@ -80,6 +97,7 @@ gd_t *global_data; " lw $25, %1($25)\n" \ " jr $25\n" \ : : "i"(offsetof(gd_t, jt)), "i"(FO(x)) : "t9"); +#endif #elif defined(CONFIG_NIOS2) /* * gp holds the pointer to the global_data, r8 is call-clobbered From 1d3d0f1f1cd8bac8ea0135c92a2bcd5020abfb1d Mon Sep 17 00:00:00 2001 From: Wills Wang Date: Wed, 16 Mar 2016 16:59:52 +0800 Subject: [PATCH 120/162] mips: add base support for QCA/Atheros ath79 SOCs This patch add some common code for QCA/Atheros ath79 SOCs such as DDR tuning, chip reset and CPU detection. Signed-off-by: Wills Wang --- arch/mips/Kconfig | 6 + arch/mips/Makefile | 1 + arch/mips/include/asm/global_data.h | 6 + arch/mips/mach-ath79/Kconfig | 7 + arch/mips/mach-ath79/Makefile | 7 + arch/mips/mach-ath79/cpu.c | 142 ++ arch/mips/mach-ath79/dram.c | 16 + .../mach-ath79/include/mach/ar71xx_regs.h | 1184 +++++++++++++++++ arch/mips/mach-ath79/include/mach/ath79.h | 143 ++ arch/mips/mach-ath79/include/mach/ddr.h | 13 + arch/mips/mach-ath79/include/mach/reset.h | 14 + arch/mips/mach-ath79/reset.c | 71 + 12 files changed, 1610 insertions(+) create mode 100644 arch/mips/mach-ath79/Kconfig create mode 100644 arch/mips/mach-ath79/Makefile create mode 100644 arch/mips/mach-ath79/cpu.c create mode 100644 arch/mips/mach-ath79/dram.c create mode 100644 arch/mips/mach-ath79/include/mach/ar71xx_regs.h create mode 100644 arch/mips/mach-ath79/include/mach/ath79.h create mode 100644 arch/mips/mach-ath79/include/mach/ddr.h create mode 100644 arch/mips/mach-ath79/include/mach/reset.h create mode 100644 arch/mips/mach-ath79/reset.c diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index fe37d1fa2d..7162f3c1ec 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -55,6 +55,11 @@ config TARGET_PB1X00 select SYS_MIPS_CACHE_INIT_RAM_LOAD select MIPS_TUNE_4KC +config ARCH_ATH79 + bool "Support QCA/Atheros ath79" + select OF_CONTROL + select DM + config MACH_PIC32 bool "Support Microchip PIC32" select OF_CONTROL @@ -67,6 +72,7 @@ source "board/imgtec/malta/Kconfig" source "board/micronas/vct/Kconfig" source "board/pb1x00/Kconfig" source "board/qemu-mips/Kconfig" +source "arch/mips/mach-ath79/Kconfig" source "arch/mips/mach-pic32/Kconfig" if MIPS diff --git a/arch/mips/Makefile b/arch/mips/Makefile index aec5a1517a..7a82316130 100644 --- a/arch/mips/Makefile +++ b/arch/mips/Makefile @@ -8,6 +8,7 @@ libs-y += arch/mips/cpu/ libs-y += arch/mips/lib/ machine-$(CONFIG_SOC_AU1X00) += au1x00 +machine-$(CONFIG_ARCH_ATH79) += ath79 machine-$(CONFIG_MACH_PIC32) += pic32 machdirs := $(patsubst %,arch/mips/mach-%/,$(machine-y)) diff --git a/arch/mips/include/asm/global_data.h b/arch/mips/include/asm/global_data.h index a1ca257db5..3f230b08f6 100644 --- a/arch/mips/include/asm/global_data.h +++ b/arch/mips/include/asm/global_data.h @@ -23,6 +23,12 @@ struct arch_global_data { unsigned long tbl; unsigned long lastinc; #endif +#ifdef CONFIG_ARCH_ATH79 + unsigned long id; + unsigned long soc; + unsigned long rev; + unsigned long ver; +#endif }; #include diff --git a/arch/mips/mach-ath79/Kconfig b/arch/mips/mach-ath79/Kconfig new file mode 100644 index 0000000000..7d8ce098be --- /dev/null +++ b/arch/mips/mach-ath79/Kconfig @@ -0,0 +1,7 @@ +menu "QCA/Atheros 7xxx/9xxx platforms" + depends on ARCH_ATH79 + +config SYS_SOC + default "ath79" + +endmenu diff --git a/arch/mips/mach-ath79/Makefile b/arch/mips/mach-ath79/Makefile new file mode 100644 index 0000000000..6203cf0242 --- /dev/null +++ b/arch/mips/mach-ath79/Makefile @@ -0,0 +1,7 @@ +# +# SPDX-License-Identifier: GPL-2.0+ +# + +obj-y += reset.o +obj-y += cpu.o +obj-y += dram.o diff --git a/arch/mips/mach-ath79/cpu.c b/arch/mips/mach-ath79/cpu.c new file mode 100644 index 0000000000..c6122f2bcc --- /dev/null +++ b/arch/mips/mach-ath79/cpu.c @@ -0,0 +1,142 @@ +/* + * Copyright (C) 2015-2016 Wills Wang + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include +#include +#include + +struct ath79_soc_desc { + enum ath79_soc_type soc; + const char *chip; + int major; + int minor; +}; + +static struct ath79_soc_desc desc[] = { + {ATH79_SOC_AR7130, "7130", + REV_ID_MAJOR_AR71XX, AR71XX_REV_ID_MINOR_AR7130}, + {ATH79_SOC_AR7141, "7141", + REV_ID_MAJOR_AR71XX, AR71XX_REV_ID_MINOR_AR7141}, + {ATH79_SOC_AR7161, "7161", + REV_ID_MAJOR_AR71XX, AR71XX_REV_ID_MINOR_AR7161}, + {ATH79_SOC_AR7240, "7240", REV_ID_MAJOR_AR7240, 0}, + {ATH79_SOC_AR7241, "7241", REV_ID_MAJOR_AR7241, 0}, + {ATH79_SOC_AR7242, "7242", REV_ID_MAJOR_AR7242, 0}, + {ATH79_SOC_AR9130, "9130", + REV_ID_MAJOR_AR913X, AR913X_REV_ID_MINOR_AR9130}, + {ATH79_SOC_AR9132, "9132", + REV_ID_MAJOR_AR913X, AR913X_REV_ID_MINOR_AR9132}, + {ATH79_SOC_AR9330, "9330", REV_ID_MAJOR_AR9330, 0}, + {ATH79_SOC_AR9331, "9331", REV_ID_MAJOR_AR9331, 0}, + {ATH79_SOC_AR9341, "9341", REV_ID_MAJOR_AR9341, 0}, + {ATH79_SOC_AR9342, "9342", REV_ID_MAJOR_AR9342, 0}, + {ATH79_SOC_AR9344, "9344", REV_ID_MAJOR_AR9344, 0}, + {ATH79_SOC_QCA9533, "9533", REV_ID_MAJOR_QCA9533, 0}, + {ATH79_SOC_QCA9533, "9533", + REV_ID_MAJOR_QCA9533_V2, 0}, + {ATH79_SOC_QCA9556, "9556", REV_ID_MAJOR_QCA9556, 0}, + {ATH79_SOC_QCA9558, "9558", REV_ID_MAJOR_QCA9558, 0}, + {ATH79_SOC_TP9343, "9343", REV_ID_MAJOR_TP9343, 0}, + {ATH79_SOC_QCA9561, "9561", REV_ID_MAJOR_QCA9561, 0}, +}; + +int arch_cpu_init(void) +{ + void __iomem *base; + enum ath79_soc_type soc = ATH79_SOC_UNKNOWN; + u32 id, major, minor = 0; + u32 rev = 0, ver = 1; + int i; + + base = map_physmem(AR71XX_RESET_BASE, AR71XX_RESET_SIZE, + MAP_NOCACHE); + + id = readl(base + AR71XX_RESET_REG_REV_ID); + major = id & REV_ID_MAJOR_MASK; + switch (major) { + case REV_ID_MAJOR_AR71XX: + case REV_ID_MAJOR_AR913X: + minor = id & AR71XX_REV_ID_MINOR_MASK; + rev = id >> AR71XX_REV_ID_REVISION_SHIFT; + rev &= AR71XX_REV_ID_REVISION_MASK; + break; + + case REV_ID_MAJOR_QCA9533_V2: + ver = 2; + /* drop through */ + + case REV_ID_MAJOR_AR9341: + case REV_ID_MAJOR_AR9342: + case REV_ID_MAJOR_AR9344: + case REV_ID_MAJOR_QCA9533: + case REV_ID_MAJOR_QCA9556: + case REV_ID_MAJOR_QCA9558: + case REV_ID_MAJOR_TP9343: + case REV_ID_MAJOR_QCA9561: + rev = id & AR71XX_REV_ID_REVISION2_MASK; + break; + default: + rev = id & AR71XX_REV_ID_REVISION_MASK; + break; + } + + for (i = 0; i < ARRAY_SIZE(desc); i++) { + if ((desc[i].major == major) && + (desc[i].minor == minor)) { + soc = desc[i].soc; + break; + } + } + + gd->arch.id = id; + gd->arch.soc = soc; + gd->arch.rev = rev; + gd->arch.ver = ver; + return 0; +} + +int print_cpuinfo(void) +{ + enum ath79_soc_type soc = ATH79_SOC_UNKNOWN; + const char *chip = "????"; + u32 id, rev, ver; + int i; + + for (i = 0; i < ARRAY_SIZE(desc); i++) { + if (desc[i].soc == gd->arch.soc) { + chip = desc[i].chip; + soc = desc[i].soc; + break; + } + } + + id = gd->arch.id; + rev = gd->arch.rev; + ver = gd->arch.ver; + + switch (soc) { + case ATH79_SOC_QCA9533: + case ATH79_SOC_QCA9556: + case ATH79_SOC_QCA9558: + case ATH79_SOC_QCA9561: + printf("Qualcomm Atheros QCA%s ver %u rev %u\n", chip, + ver, rev); + break; + case ATH79_SOC_TP9343: + printf("Qualcomm Atheros TP%s rev %u\n", chip, rev); + break; + case ATH79_SOC_UNKNOWN: + printf("ATH79: unknown SoC, id:0x%08x", id); + break; + default: + printf("Atheros AR%s rev %u\n", chip, rev); + } + + return 0; +} diff --git a/arch/mips/mach-ath79/dram.c b/arch/mips/mach-ath79/dram.c new file mode 100644 index 0000000000..c29e98c2f4 --- /dev/null +++ b/arch/mips/mach-ath79/dram.c @@ -0,0 +1,16 @@ +/* + * Copyright (C) 2015-2016 Wills Wang + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include + +phys_size_t initdram(int board_type) +{ + ddr_tap_tuning(); + return get_ram_size((void *)KSEG1, SZ_256M); +} diff --git a/arch/mips/mach-ath79/include/mach/ar71xx_regs.h b/arch/mips/mach-ath79/include/mach/ar71xx_regs.h new file mode 100644 index 0000000000..893dedc2a4 --- /dev/null +++ b/arch/mips/mach-ath79/include/mach/ar71xx_regs.h @@ -0,0 +1,1184 @@ +/* + * Atheros AR71XX/AR724X/AR913X SoC register definitions + * + * Copyright (C) 2015-2016 Wills Wang + * Copyright (C) 2010-2011 Jaiganesh Narayanan + * Copyright (C) 2008-2010 Gabor Juhos + * Copyright (C) 2008 Imre Kaloz + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef __ASM_MACH_AR71XX_REGS_H +#define __ASM_MACH_AR71XX_REGS_H + +#ifndef __ASSEMBLY__ +#include +#else +#ifndef BIT +#define BIT(nr) (1 << (nr)) +#endif +#endif + +#define AR71XX_APB_BASE 0x18000000 +#define AR71XX_GE0_BASE 0x19000000 +#define AR71XX_GE0_SIZE 0x10000 +#define AR71XX_GE1_BASE 0x1a000000 +#define AR71XX_GE1_SIZE 0x10000 +#define AR71XX_EHCI_BASE 0x1b000000 +#define AR71XX_EHCI_SIZE 0x1000 +#define AR71XX_OHCI_BASE 0x1c000000 +#define AR71XX_OHCI_SIZE 0x1000 +#define AR71XX_SPI_BASE 0x1f000000 +#define AR71XX_SPI_SIZE 0x01000000 + +#define AR71XX_DDR_CTRL_BASE (AR71XX_APB_BASE + 0x00000000) +#define AR71XX_DDR_CTRL_SIZE 0x100 +#define AR71XX_UART_BASE (AR71XX_APB_BASE + 0x00020000) +#define AR71XX_UART_SIZE 0x100 +#define AR71XX_USB_CTRL_BASE (AR71XX_APB_BASE + 0x00030000) +#define AR71XX_USB_CTRL_SIZE 0x100 +#define AR71XX_GPIO_BASE (AR71XX_APB_BASE + 0x00040000) +#define AR71XX_GPIO_SIZE 0x100 +#define AR71XX_PLL_BASE (AR71XX_APB_BASE + 0x00050000) +#define AR71XX_PLL_SIZE 0x100 +#define AR71XX_RESET_BASE (AR71XX_APB_BASE + 0x00060000) +#define AR71XX_RESET_SIZE 0x100 +#define AR71XX_MII_BASE (AR71XX_APB_BASE + 0x00070000) +#define AR71XX_MII_SIZE 0x100 + +#define AR71XX_PCI_MEM_BASE 0x10000000 +#define AR71XX_PCI_MEM_SIZE 0x07000000 + +#define AR71XX_PCI_WIN0_OFFS 0x10000000 +#define AR71XX_PCI_WIN1_OFFS 0x11000000 +#define AR71XX_PCI_WIN2_OFFS 0x12000000 +#define AR71XX_PCI_WIN3_OFFS 0x13000000 +#define AR71XX_PCI_WIN4_OFFS 0x14000000 +#define AR71XX_PCI_WIN5_OFFS 0x15000000 +#define AR71XX_PCI_WIN6_OFFS 0x16000000 +#define AR71XX_PCI_WIN7_OFFS 0x07000000 + +#define AR71XX_PCI_CFG_BASE \ + (AR71XX_PCI_MEM_BASE + AR71XX_PCI_WIN7_OFFS + 0x10000) +#define AR71XX_PCI_CFG_SIZE 0x100 + +#define AR7240_USB_CTRL_BASE (AR71XX_APB_BASE + 0x00030000) +#define AR7240_USB_CTRL_SIZE 0x100 +#define AR7240_OHCI_BASE 0x1b000000 +#define AR7240_OHCI_SIZE 0x1000 + +#define AR724X_PCI_MEM_BASE 0x10000000 +#define AR724X_PCI_MEM_SIZE 0x04000000 + +#define AR724X_PCI_CFG_BASE 0x14000000 +#define AR724X_PCI_CFG_SIZE 0x1000 +#define AR724X_PCI_CRP_BASE (AR71XX_APB_BASE + 0x000c0000) +#define AR724X_PCI_CRP_SIZE 0x1000 +#define AR724X_PCI_CTRL_BASE (AR71XX_APB_BASE + 0x000f0000) +#define AR724X_PCI_CTRL_SIZE 0x100 + +#define AR724X_EHCI_BASE 0x1b000000 +#define AR724X_EHCI_SIZE 0x1000 + +#define AR913X_EHCI_BASE 0x1b000000 +#define AR913X_EHCI_SIZE 0x1000 +#define AR913X_WMAC_BASE (AR71XX_APB_BASE + 0x000C0000) +#define AR913X_WMAC_SIZE 0x30000 + +#define AR933X_UART_BASE (AR71XX_APB_BASE + 0x00020000) +#define AR933X_UART_SIZE 0x14 +#define AR933X_GMAC_BASE (AR71XX_APB_BASE + 0x00070000) +#define AR933X_GMAC_SIZE 0x04 +#define AR933X_WMAC_BASE (AR71XX_APB_BASE + 0x00100000) +#define AR933X_WMAC_SIZE 0x20000 +#define AR933X_RTC_BASE (AR71XX_APB_BASE + 0x00107000) +#define AR933X_RTC_SIZE 0x1000 +#define AR933X_EHCI_BASE 0x1b000000 +#define AR933X_EHCI_SIZE 0x1000 +#define AR933X_SRIF_BASE (AR71XX_APB_BASE + 0x00116000) +#define AR933X_SRIF_SIZE 0x1000 + +#define AR934X_GMAC_BASE (AR71XX_APB_BASE + 0x00070000) +#define AR934X_GMAC_SIZE 0x14 +#define AR934X_WMAC_BASE (AR71XX_APB_BASE + 0x00100000) +#define AR934X_WMAC_SIZE 0x20000 +#define AR934X_EHCI_BASE 0x1b000000 +#define AR934X_EHCI_SIZE 0x200 +#define AR934X_NFC_BASE 0x1b000200 +#define AR934X_NFC_SIZE 0xb8 +#define AR934X_SRIF_BASE (AR71XX_APB_BASE + 0x00116000) +#define AR934X_SRIF_SIZE 0x1000 + +#define QCA953X_GMAC_BASE (AR71XX_APB_BASE + 0x00070000) +#define QCA953X_GMAC_SIZE 0x14 +#define QCA953X_WMAC_BASE (AR71XX_APB_BASE + 0x00100000) +#define QCA953X_WMAC_SIZE 0x20000 +#define QCA953X_RTC_BASE (AR71XX_APB_BASE + 0x00107000) +#define QCA953X_RTC_SIZE 0x1000 +#define QCA953X_EHCI_BASE 0x1b000000 +#define QCA953X_EHCI_SIZE 0x200 +#define QCA953X_SRIF_BASE (AR71XX_APB_BASE + 0x00116000) +#define QCA953X_SRIF_SIZE 0x1000 + +#define QCA953X_PCI_CFG_BASE0 0x14000000 +#define QCA953X_PCI_CTRL_BASE0 (AR71XX_APB_BASE + 0x000f0000) +#define QCA953X_PCI_CRP_BASE0 (AR71XX_APB_BASE + 0x000c0000) +#define QCA953X_PCI_MEM_BASE0 0x10000000 +#define QCA953X_PCI_MEM_SIZE 0x02000000 + +#define QCA955X_PCI_MEM_BASE0 0x10000000 +#define QCA955X_PCI_MEM_BASE1 0x12000000 +#define QCA955X_PCI_MEM_SIZE 0x02000000 +#define QCA955X_PCI_CFG_BASE0 0x14000000 +#define QCA955X_PCI_CFG_BASE1 0x16000000 +#define QCA955X_PCI_CFG_SIZE 0x1000 +#define QCA955X_PCI_CRP_BASE0 (AR71XX_APB_BASE + 0x000c0000) +#define QCA955X_PCI_CRP_BASE1 (AR71XX_APB_BASE + 0x00250000) +#define QCA955X_PCI_CRP_SIZE 0x1000 +#define QCA955X_PCI_CTRL_BASE0 (AR71XX_APB_BASE + 0x000f0000) +#define QCA955X_PCI_CTRL_BASE1 (AR71XX_APB_BASE + 0x00280000) +#define QCA955X_PCI_CTRL_SIZE 0x100 + +#define QCA955X_GMAC_BASE (AR71XX_APB_BASE + 0x00070000) +#define QCA955X_GMAC_SIZE 0x40 +#define QCA955X_WMAC_BASE (AR71XX_APB_BASE + 0x00100000) +#define QCA955X_WMAC_SIZE 0x20000 +#define QCA955X_EHCI0_BASE 0x1b000000 +#define QCA955X_EHCI1_BASE 0x1b400000 +#define QCA955X_EHCI_SIZE 0x1000 +#define QCA955X_NFC_BASE 0x1b800200 +#define QCA955X_NFC_SIZE 0xb8 + +#define QCA956X_PCI_MEM_BASE1 0x12000000 +#define QCA956X_PCI_MEM_SIZE 0x02000000 +#define QCA956X_PCI_CFG_BASE1 0x16000000 +#define QCA956X_PCI_CFG_SIZE 0x1000 +#define QCA956X_PCI_CRP_BASE1 (AR71XX_APB_BASE + 0x00250000) +#define QCA956X_PCI_CRP_SIZE 0x1000 +#define QCA956X_PCI_CTRL_BASE1 (AR71XX_APB_BASE + 0x00280000) +#define QCA956X_PCI_CTRL_SIZE 0x100 + +#define QCA956X_WMAC_BASE (AR71XX_APB_BASE + 0x00100000) +#define QCA956X_WMAC_SIZE 0x20000 +#define QCA956X_EHCI0_BASE 0x1b000000 +#define QCA956X_EHCI1_BASE 0x1b400000 +#define QCA956X_EHCI_SIZE 0x200 +#define QCA956X_GMAC_BASE (AR71XX_APB_BASE + 0x00070000) +#define QCA956X_GMAC_SIZE 0x64 + +/* + * DDR_CTRL block + */ +#define AR71XX_DDR_REG_CONFIG 0x00 +#define AR71XX_DDR_REG_CONFIG2 0x04 +#define AR71XX_DDR_REG_MODE 0x08 +#define AR71XX_DDR_REG_EMR 0x0c +#define AR71XX_DDR_REG_CONTROL 0x10 +#define AR71XX_DDR_REG_REFRESH 0x14 +#define AR71XX_DDR_REG_RD_CYCLE 0x18 +#define AR71XX_DDR_REG_TAP_CTRL0 0x1c +#define AR71XX_DDR_REG_TAP_CTRL1 0x20 + +#define AR71XX_DDR_REG_PCI_WIN0 0x7c +#define AR71XX_DDR_REG_PCI_WIN1 0x80 +#define AR71XX_DDR_REG_PCI_WIN2 0x84 +#define AR71XX_DDR_REG_PCI_WIN3 0x88 +#define AR71XX_DDR_REG_PCI_WIN4 0x8c +#define AR71XX_DDR_REG_PCI_WIN5 0x90 +#define AR71XX_DDR_REG_PCI_WIN6 0x94 +#define AR71XX_DDR_REG_PCI_WIN7 0x98 +#define AR71XX_DDR_REG_FLUSH_GE0 0x9c +#define AR71XX_DDR_REG_FLUSH_GE1 0xa0 +#define AR71XX_DDR_REG_FLUSH_USB 0xa4 +#define AR71XX_DDR_REG_FLUSH_PCI 0xa8 + +#define AR724X_DDR_REG_FLUSH_GE0 0x7c +#define AR724X_DDR_REG_FLUSH_GE1 0x80 +#define AR724X_DDR_REG_FLUSH_USB 0x84 +#define AR724X_DDR_REG_FLUSH_PCIE 0x88 + +#define AR913X_DDR_REG_FLUSH_GE0 0x7c +#define AR913X_DDR_REG_FLUSH_GE1 0x80 +#define AR913X_DDR_REG_FLUSH_USB 0x84 +#define AR913X_DDR_REG_FLUSH_WMAC 0x88 + +#define AR933X_DDR_REG_FLUSH_GE0 0x7c +#define AR933X_DDR_REG_FLUSH_GE1 0x80 +#define AR933X_DDR_REG_FLUSH_USB 0x84 +#define AR933X_DDR_REG_FLUSH_WMAC 0x88 +#define AR933X_DDR_REG_DDR2_CONFIG 0x8c +#define AR933X_DDR_REG_EMR2 0x90 +#define AR933X_DDR_REG_EMR3 0x94 +#define AR933X_DDR_REG_BURST 0x98 +#define AR933X_DDR_REG_TIMEOUT_MAX 0x9c +#define AR933X_DDR_REG_TIMEOUT_CNT 0x9c +#define AR933X_DDR_REG_TIMEOUT_ADDR 0x9c + +#define AR934X_DDR_REG_FLUSH_GE0 0x9c +#define AR934X_DDR_REG_FLUSH_GE1 0xa0 +#define AR934X_DDR_REG_FLUSH_USB 0xa4 +#define AR934X_DDR_REG_FLUSH_PCIE 0xa8 +#define AR934X_DDR_REG_FLUSH_WMAC 0xac + +#define QCA953X_DDR_REG_FLUSH_GE0 0x9c +#define QCA953X_DDR_REG_FLUSH_GE1 0xa0 +#define QCA953X_DDR_REG_FLUSH_USB 0xa4 +#define QCA953X_DDR_REG_FLUSH_PCIE 0xa8 +#define QCA953X_DDR_REG_FLUSH_WMAC 0xac +#define QCA953X_DDR_REG_DDR2_CONFIG 0xb8 +#define QCA953X_DDR_REG_BURST 0xc4 +#define QCA953X_DDR_REG_BURST2 0xc8 +#define QCA953X_DDR_REG_TIMEOUT_MAX 0xcc +#define QCA953X_DDR_REG_CTL_CONF 0x108 +#define QCA953X_DDR_REG_CONFIG3 0x15c + +/* + * PLL block + */ +#define AR71XX_PLL_REG_CPU_CONFIG 0x00 +#define AR71XX_PLL_REG_SEC_CONFIG 0x04 +#define AR71XX_PLL_REG_ETH0_INT_CLOCK 0x10 +#define AR71XX_PLL_REG_ETH1_INT_CLOCK 0x14 + +#define AR71XX_PLL_DIV_SHIFT 3 +#define AR71XX_PLL_DIV_MASK 0x1f +#define AR71XX_CPU_DIV_SHIFT 16 +#define AR71XX_CPU_DIV_MASK 0x3 +#define AR71XX_DDR_DIV_SHIFT 18 +#define AR71XX_DDR_DIV_MASK 0x3 +#define AR71XX_AHB_DIV_SHIFT 20 +#define AR71XX_AHB_DIV_MASK 0x7 + +#define AR71XX_ETH0_PLL_SHIFT 17 +#define AR71XX_ETH1_PLL_SHIFT 19 + +#define AR724X_PLL_REG_CPU_CONFIG 0x00 +#define AR724X_PLL_REG_PCIE_CONFIG 0x18 + +#define AR724X_PLL_DIV_SHIFT 0 +#define AR724X_PLL_DIV_MASK 0x3ff +#define AR724X_PLL_REF_DIV_SHIFT 10 +#define AR724X_PLL_REF_DIV_MASK 0xf +#define AR724X_AHB_DIV_SHIFT 19 +#define AR724X_AHB_DIV_MASK 0x1 +#define AR724X_DDR_DIV_SHIFT 22 +#define AR724X_DDR_DIV_MASK 0x3 + +#define AR7242_PLL_REG_ETH0_INT_CLOCK 0x2c + +#define AR913X_PLL_REG_CPU_CONFIG 0x00 +#define AR913X_PLL_REG_ETH_CONFIG 0x04 +#define AR913X_PLL_REG_ETH0_INT_CLOCK 0x14 +#define AR913X_PLL_REG_ETH1_INT_CLOCK 0x18 + +#define AR913X_PLL_DIV_SHIFT 0 +#define AR913X_PLL_DIV_MASK 0x3ff +#define AR913X_DDR_DIV_SHIFT 22 +#define AR913X_DDR_DIV_MASK 0x3 +#define AR913X_AHB_DIV_SHIFT 19 +#define AR913X_AHB_DIV_MASK 0x1 + +#define AR913X_ETH0_PLL_SHIFT 20 +#define AR913X_ETH1_PLL_SHIFT 22 + +#define AR933X_PLL_CPU_CONFIG_REG 0x00 +#define AR933X_PLL_CLK_CTRL_REG 0x08 +#define AR933X_PLL_DITHER_FRAC_REG 0x10 + +#define AR933X_PLL_CPU_CONFIG_NINT_SHIFT 10 +#define AR933X_PLL_CPU_CONFIG_NINT_MASK 0x3f +#define AR933X_PLL_CPU_CONFIG_REFDIV_SHIFT 16 +#define AR933X_PLL_CPU_CONFIG_REFDIV_MASK 0x1f +#define AR933X_PLL_CPU_CONFIG_OUTDIV_SHIFT 23 +#define AR933X_PLL_CPU_CONFIG_OUTDIV_MASK 0x7 + +#define AR933X_PLL_CLK_CTRL_BYPASS BIT(2) +#define AR933X_PLL_CLK_CTRL_CPU_POST_DIV_SHIFT 5 +#define AR933X_PLL_CLK_CTRL_CPU_POST_DIV_MASK 0x3 +#define AR933X_PLL_CLK_CTRL_DDR_POST_DIV_SHIFT 10 +#define AR933X_PLL_CLK_CTRL_DDR_POST_DIV_MASK 0x3 +#define AR933X_PLL_CLK_CTRL_AHB_POST_DIV_SHIFT 15 +#define AR933X_PLL_CLK_CTRL_AHB_POST_DIV_MASK 0x7 + +#define AR934X_PLL_CPU_CONFIG_REG 0x00 +#define AR934X_PLL_DDR_CONFIG_REG 0x04 +#define AR934X_PLL_CPU_DDR_CLK_CTRL_REG 0x08 +#define AR934X_PLL_SWITCH_CLOCK_CONTROL_REG 0x24 +#define AR934X_PLL_ETH_XMII_CONTROL_REG 0x2c + +#define AR934X_PLL_CPU_CONFIG_NFRAC_SHIFT 0 +#define AR934X_PLL_CPU_CONFIG_NFRAC_MASK 0x3f +#define AR934X_PLL_CPU_CONFIG_NINT_SHIFT 6 +#define AR934X_PLL_CPU_CONFIG_NINT_MASK 0x3f +#define AR934X_PLL_CPU_CONFIG_REFDIV_SHIFT 12 +#define AR934X_PLL_CPU_CONFIG_REFDIV_MASK 0x1f +#define AR934X_PLL_CPU_CONFIG_OUTDIV_SHIFT 19 +#define AR934X_PLL_CPU_CONFIG_OUTDIV_MASK 0x3 + +#define AR934X_PLL_DDR_CONFIG_NFRAC_SHIFT 0 +#define AR934X_PLL_DDR_CONFIG_NFRAC_MASK 0x3ff +#define AR934X_PLL_DDR_CONFIG_NINT_SHIFT 10 +#define AR934X_PLL_DDR_CONFIG_NINT_MASK 0x3f +#define AR934X_PLL_DDR_CONFIG_REFDIV_SHIFT 16 +#define AR934X_PLL_DDR_CONFIG_REFDIV_MASK 0x1f +#define AR934X_PLL_DDR_CONFIG_OUTDIV_SHIFT 23 +#define AR934X_PLL_DDR_CONFIG_OUTDIV_MASK 0x7 + +#define AR934X_PLL_CLK_CTRL_CPU_PLL_BYPASS BIT(2) +#define AR934X_PLL_CLK_CTRL_DDR_PLL_BYPASS BIT(3) +#define AR934X_PLL_CLK_CTRL_AHB_PLL_BYPASS BIT(4) +#define AR934X_PLL_CLK_CTRL_CPU_POST_DIV_SHIFT 5 +#define AR934X_PLL_CLK_CTRL_CPU_POST_DIV_MASK 0x1f +#define AR934X_PLL_CLK_CTRL_DDR_POST_DIV_SHIFT 10 +#define AR934X_PLL_CLK_CTRL_DDR_POST_DIV_MASK 0x1f +#define AR934X_PLL_CLK_CTRL_AHB_POST_DIV_SHIFT 15 +#define AR934X_PLL_CLK_CTRL_AHB_POST_DIV_MASK 0x1f +#define AR934X_PLL_CLK_CTRL_CPUCLK_FROM_CPUPLL BIT(20) +#define AR934X_PLL_CLK_CTRL_DDRCLK_FROM_DDRPLL BIT(21) +#define AR934X_PLL_CLK_CTRL_AHBCLK_FROM_DDRPLL BIT(24) + +#define AR934X_PLL_SWITCH_CLK_CTRL_MDIO_CLK_SEL BIT(6) + +#define QCA953X_PLL_CPU_CONFIG_REG 0x00 +#define QCA953X_PLL_DDR_CONFIG_REG 0x04 +#define QCA953X_PLL_CLK_CTRL_REG 0x08 +#define QCA953X_PLL_SWITCH_CLOCK_CONTROL_REG 0x24 +#define QCA953X_PLL_ETH_XMII_CONTROL_REG 0x2c +#define QCA953X_PLL_DDR_DIT_FRAC_REG 0x44 +#define QCA953X_PLL_CPU_DIT_FRAC_REG 0x48 + +#define QCA953X_PLL_CPU_CONFIG_NFRAC_SHIFT 0 +#define QCA953X_PLL_CPU_CONFIG_NFRAC_MASK 0x3f +#define QCA953X_PLL_CPU_CONFIG_NINT_SHIFT 6 +#define QCA953X_PLL_CPU_CONFIG_NINT_MASK 0x3f +#define QCA953X_PLL_CPU_CONFIG_REFDIV_SHIFT 12 +#define QCA953X_PLL_CPU_CONFIG_REFDIV_MASK 0x1f +#define QCA953X_PLL_CPU_CONFIG_OUTDIV_SHIFT 19 +#define QCA953X_PLL_CPU_CONFIG_OUTDIV_MASK 0x7 + +#define QCA953X_PLL_DDR_CONFIG_NFRAC_SHIFT 0 +#define QCA953X_PLL_DDR_CONFIG_NFRAC_MASK 0x3ff +#define QCA953X_PLL_DDR_CONFIG_NINT_SHIFT 10 +#define QCA953X_PLL_DDR_CONFIG_NINT_MASK 0x3f +#define QCA953X_PLL_DDR_CONFIG_REFDIV_SHIFT 16 +#define QCA953X_PLL_DDR_CONFIG_REFDIV_MASK 0x1f +#define QCA953X_PLL_DDR_CONFIG_OUTDIV_SHIFT 23 +#define QCA953X_PLL_DDR_CONFIG_OUTDIV_MASK 0x7 + +#define QCA953X_PLL_CONFIG_PWD BIT(30) + +#define QCA953X_PLL_CLK_CTRL_CPU_PLL_BYPASS BIT(2) +#define QCA953X_PLL_CLK_CTRL_DDR_PLL_BYPASS BIT(3) +#define QCA953X_PLL_CLK_CTRL_AHB_PLL_BYPASS BIT(4) +#define QCA953X_PLL_CLK_CTRL_CPU_POST_DIV_SHIFT 5 +#define QCA953X_PLL_CLK_CTRL_CPU_POST_DIV_MASK 0x1f +#define QCA953X_PLL_CLK_CTRL_DDR_POST_DIV_SHIFT 10 +#define QCA953X_PLL_CLK_CTRL_DDR_POST_DIV_MASK 0x1f +#define QCA953X_PLL_CLK_CTRL_AHB_POST_DIV_SHIFT 15 +#define QCA953X_PLL_CLK_CTRL_AHB_POST_DIV_MASK 0x1f +#define QCA953X_PLL_CLK_CTRL_CPUCLK_FROM_CPUPLL BIT(20) +#define QCA953X_PLL_CLK_CTRL_DDRCLK_FROM_DDRPLL BIT(21) +#define QCA953X_PLL_CLK_CTRL_AHBCLK_FROM_DDRPLL BIT(24) + +#define QCA953X_PLL_CPU_DIT_FRAC_MAX_SHIFT 0 +#define QCA953X_PLL_CPU_DIT_FRAC_MAX_MASK 0x3f +#define QCA953X_PLL_CPU_DIT_FRAC_MIN_SHIFT 6 +#define QCA953X_PLL_CPU_DIT_FRAC_MIN_MASK 0x3f +#define QCA953X_PLL_CPU_DIT_FRAC_STEP_SHIFT 12 +#define QCA953X_PLL_CPU_DIT_FRAC_STEP_MASK 0x3f +#define QCA953X_PLL_CPU_DIT_UPD_CNT_SHIFT 18 +#define QCA953X_PLL_CPU_DIT_UPD_CNT_MASK 0x3f + +#define QCA953X_PLL_DDR_DIT_FRAC_MAX_SHIFT 0 +#define QCA953X_PLL_DDR_DIT_FRAC_MAX_MASK 0x3ff +#define QCA953X_PLL_DDR_DIT_FRAC_MIN_SHIFT 9 +#define QCA953X_PLL_DDR_DIT_FRAC_MIN_MASK 0x3ff +#define QCA953X_PLL_DDR_DIT_FRAC_STEP_SHIFT 20 +#define QCA953X_PLL_DDR_DIT_FRAC_STEP_MASK 0x3f +#define QCA953X_PLL_DDR_DIT_UPD_CNT_SHIFT 27 +#define QCA953X_PLL_DDR_DIT_UPD_CNT_MASK 0x3f + +#define QCA953X_PLL_DIT_FRAC_EN BIT(31) + +#define QCA955X_PLL_CPU_CONFIG_REG 0x00 +#define QCA955X_PLL_DDR_CONFIG_REG 0x04 +#define QCA955X_PLL_CLK_CTRL_REG 0x08 +#define QCA955X_PLL_ETH_XMII_CONTROL_REG 0x28 +#define QCA955X_PLL_ETH_SGMII_CONTROL_REG 0x48 + +#define QCA955X_PLL_CPU_CONFIG_NFRAC_SHIFT 0 +#define QCA955X_PLL_CPU_CONFIG_NFRAC_MASK 0x3f +#define QCA955X_PLL_CPU_CONFIG_NINT_SHIFT 6 +#define QCA955X_PLL_CPU_CONFIG_NINT_MASK 0x3f +#define QCA955X_PLL_CPU_CONFIG_REFDIV_SHIFT 12 +#define QCA955X_PLL_CPU_CONFIG_REFDIV_MASK 0x1f +#define QCA955X_PLL_CPU_CONFIG_OUTDIV_SHIFT 19 +#define QCA955X_PLL_CPU_CONFIG_OUTDIV_MASK 0x3 + +#define QCA955X_PLL_DDR_CONFIG_NFRAC_SHIFT 0 +#define QCA955X_PLL_DDR_CONFIG_NFRAC_MASK 0x3ff +#define QCA955X_PLL_DDR_CONFIG_NINT_SHIFT 10 +#define QCA955X_PLL_DDR_CONFIG_NINT_MASK 0x3f +#define QCA955X_PLL_DDR_CONFIG_REFDIV_SHIFT 16 +#define QCA955X_PLL_DDR_CONFIG_REFDIV_MASK 0x1f +#define QCA955X_PLL_DDR_CONFIG_OUTDIV_SHIFT 23 +#define QCA955X_PLL_DDR_CONFIG_OUTDIV_MASK 0x7 + +#define QCA955X_PLL_CLK_CTRL_CPU_PLL_BYPASS BIT(2) +#define QCA955X_PLL_CLK_CTRL_DDR_PLL_BYPASS BIT(3) +#define QCA955X_PLL_CLK_CTRL_AHB_PLL_BYPASS BIT(4) +#define QCA955X_PLL_CLK_CTRL_CPU_POST_DIV_SHIFT 5 +#define QCA955X_PLL_CLK_CTRL_CPU_POST_DIV_MASK 0x1f +#define QCA955X_PLL_CLK_CTRL_DDR_POST_DIV_SHIFT 10 +#define QCA955X_PLL_CLK_CTRL_DDR_POST_DIV_MASK 0x1f +#define QCA955X_PLL_CLK_CTRL_AHB_POST_DIV_SHIFT 15 +#define QCA955X_PLL_CLK_CTRL_AHB_POST_DIV_MASK 0x1f +#define QCA955X_PLL_CLK_CTRL_CPUCLK_FROM_CPUPLL BIT(20) +#define QCA955X_PLL_CLK_CTRL_DDRCLK_FROM_DDRPLL BIT(21) +#define QCA955X_PLL_CLK_CTRL_AHBCLK_FROM_DDRPLL BIT(24) + +#define QCA956X_PLL_CPU_CONFIG_REG 0x00 +#define QCA956X_PLL_CPU_CONFIG1_REG 0x04 +#define QCA956X_PLL_DDR_CONFIG_REG 0x08 +#define QCA956X_PLL_DDR_CONFIG1_REG 0x0c +#define QCA956X_PLL_CLK_CTRL_REG 0x10 + +#define QCA956X_PLL_CPU_CONFIG_REFDIV_SHIFT 12 +#define QCA956X_PLL_CPU_CONFIG_REFDIV_MASK 0x1f +#define QCA956X_PLL_CPU_CONFIG_OUTDIV_SHIFT 19 +#define QCA956X_PLL_CPU_CONFIG_OUTDIV_MASK 0x7 + +#define QCA956X_PLL_CPU_CONFIG1_NFRAC_L_SHIFT 0 +#define QCA956X_PLL_CPU_CONFIG1_NFRAC_L_MASK 0x1f +#define QCA956X_PLL_CPU_CONFIG1_NFRAC_H_SHIFT 5 +#define QCA956X_PLL_CPU_CONFIG1_NFRAC_H_MASK 0x3fff +#define QCA956X_PLL_CPU_CONFIG1_NINT_SHIFT 18 +#define QCA956X_PLL_CPU_CONFIG1_NINT_MASK 0x1ff + +#define QCA956X_PLL_DDR_CONFIG_REFDIV_SHIFT 16 +#define QCA956X_PLL_DDR_CONFIG_REFDIV_MASK 0x1f +#define QCA956X_PLL_DDR_CONFIG_OUTDIV_SHIFT 23 +#define QCA956X_PLL_DDR_CONFIG_OUTDIV_MASK 0x7 + +#define QCA956X_PLL_DDR_CONFIG1_NFRAC_L_SHIFT 0 +#define QCA956X_PLL_DDR_CONFIG1_NFRAC_L_MASK 0x1f +#define QCA956X_PLL_DDR_CONFIG1_NFRAC_H_SHIFT 5 +#define QCA956X_PLL_DDR_CONFIG1_NFRAC_H_MASK 0x3fff +#define QCA956X_PLL_DDR_CONFIG1_NINT_SHIFT 18 +#define QCA956X_PLL_DDR_CONFIG1_NINT_MASK 0x1ff + +#define QCA956X_PLL_CLK_CTRL_CPU_PLL_BYPASS BIT(2) +#define QCA956X_PLL_CLK_CTRL_DDR_PLL_BYPASS BIT(3) +#define QCA956X_PLL_CLK_CTRL_AHB_PLL_BYPASS BIT(4) +#define QCA956X_PLL_CLK_CTRL_CPU_POST_DIV_SHIFT 5 +#define QCA956X_PLL_CLK_CTRL_CPU_POST_DIV_MASK 0x1f +#define QCA956X_PLL_CLK_CTRL_DDR_POST_DIV_SHIFT 10 +#define QCA956X_PLL_CLK_CTRL_DDR_POST_DIV_MASK 0x1f +#define QCA956X_PLL_CLK_CTRL_AHB_POST_DIV_SHIFT 15 +#define QCA956X_PLL_CLK_CTRL_AHB_POST_DIV_MASK 0x1f +#define QCA956X_PLL_CLK_CTRL_CPU_DDRCLK_FROM_DDRPLL BIT(20) +#define QCA956X_PLL_CLK_CTRL_CPU_DDRCLK_FROM_CPUPLL BIT(21) +#define QCA956X_PLL_CLK_CTRL_AHBCLK_FROM_DDRPLL BIT(24) + +/* + * USB_CONFIG block + */ +#define AR71XX_USB_CTRL_REG_FLADJ 0x00 +#define AR71XX_USB_CTRL_REG_CONFIG 0x04 + +/* + * RESET block + */ +#define AR71XX_RESET_REG_TIMER 0x00 +#define AR71XX_RESET_REG_TIMER_RELOAD 0x04 +#define AR71XX_RESET_REG_WDOG_CTRL 0x08 +#define AR71XX_RESET_REG_WDOG 0x0c +#define AR71XX_RESET_REG_MISC_INT_STATUS 0x10 +#define AR71XX_RESET_REG_MISC_INT_ENABLE 0x14 +#define AR71XX_RESET_REG_PCI_INT_STATUS 0x18 +#define AR71XX_RESET_REG_PCI_INT_ENABLE 0x1c +#define AR71XX_RESET_REG_GLOBAL_INT_STATUS 0x20 +#define AR71XX_RESET_REG_RESET_MODULE 0x24 +#define AR71XX_RESET_REG_PERFC_CTRL 0x2c +#define AR71XX_RESET_REG_PERFC0 0x30 +#define AR71XX_RESET_REG_PERFC1 0x34 +#define AR71XX_RESET_REG_REV_ID 0x90 + +#define AR913X_RESET_REG_GLOBAL_INT_STATUS 0x18 +#define AR913X_RESET_REG_RESET_MODULE 0x1c +#define AR913X_RESET_REG_PERF_CTRL 0x20 +#define AR913X_RESET_REG_PERFC0 0x24 +#define AR913X_RESET_REG_PERFC1 0x28 + +#define AR724X_RESET_REG_RESET_MODULE 0x1c + +#define AR933X_RESET_REG_RESET_MODULE 0x1c +#define AR933X_RESET_REG_BOOTSTRAP 0xac + +#define AR934X_RESET_REG_RESET_MODULE 0x1c +#define AR934X_RESET_REG_BOOTSTRAP 0xb0 +#define AR934X_RESET_REG_PCIE_WMAC_INT_STATUS 0xac + +#define QCA953X_RESET_REG_RESET_MODULE 0x1c +#define QCA953X_RESET_REG_BOOTSTRAP 0xb0 +#define QCA953X_RESET_REG_PCIE_WMAC_INT_STATUS 0xac + +#define QCA955X_RESET_REG_RESET_MODULE 0x1c +#define QCA955X_RESET_REG_BOOTSTRAP 0xb0 +#define QCA955X_RESET_REG_EXT_INT_STATUS 0xac + +#define QCA956X_RESET_REG_RESET_MODULE 0x1c +#define QCA956X_RESET_REG_BOOTSTRAP 0xb0 +#define QCA956X_RESET_REG_EXT_INT_STATUS 0xac + +#define MISC_INT_MIPS_SI_TIMERINT_MASK BIT(28) +#define MISC_INT_ETHSW BIT(12) +#define MISC_INT_TIMER4 BIT(10) +#define MISC_INT_TIMER3 BIT(9) +#define MISC_INT_TIMER2 BIT(8) +#define MISC_INT_DMA BIT(7) +#define MISC_INT_OHCI BIT(6) +#define MISC_INT_PERFC BIT(5) +#define MISC_INT_WDOG BIT(4) +#define MISC_INT_UART BIT(3) +#define MISC_INT_GPIO BIT(2) +#define MISC_INT_ERROR BIT(1) +#define MISC_INT_TIMER BIT(0) + +#define AR71XX_RESET_EXTERNAL BIT(28) +#define AR71XX_RESET_FULL_CHIP BIT(24) +#define AR71XX_RESET_CPU_NMI BIT(21) +#define AR71XX_RESET_CPU_COLD BIT(20) +#define AR71XX_RESET_DMA BIT(19) +#define AR71XX_RESET_SLIC BIT(18) +#define AR71XX_RESET_STEREO BIT(17) +#define AR71XX_RESET_DDR BIT(16) +#define AR71XX_RESET_GE1_MAC BIT(13) +#define AR71XX_RESET_GE1_PHY BIT(12) +#define AR71XX_RESET_USBSUS_OVERRIDE BIT(10) +#define AR71XX_RESET_GE0_MAC BIT(9) +#define AR71XX_RESET_GE0_PHY BIT(8) +#define AR71XX_RESET_USB_OHCI_DLL BIT(6) +#define AR71XX_RESET_USB_HOST BIT(5) +#define AR71XX_RESET_USB_PHY BIT(4) +#define AR71XX_RESET_PCI_BUS BIT(1) +#define AR71XX_RESET_PCI_CORE BIT(0) + +#define AR7240_RESET_USB_HOST BIT(5) +#define AR7240_RESET_OHCI_DLL BIT(3) + +#define AR724X_RESET_GE1_MDIO BIT(23) +#define AR724X_RESET_GE0_MDIO BIT(22) +#define AR724X_RESET_PCIE_PHY_SERIAL BIT(10) +#define AR724X_RESET_PCIE_PHY BIT(7) +#define AR724X_RESET_PCIE BIT(6) +#define AR724X_RESET_USB_HOST BIT(5) +#define AR724X_RESET_USB_PHY BIT(4) +#define AR724X_RESET_USBSUS_OVERRIDE BIT(3) + +#define AR913X_RESET_AMBA2WMAC BIT(22) +#define AR913X_RESET_USBSUS_OVERRIDE BIT(10) +#define AR913X_RESET_USB_HOST BIT(5) +#define AR913X_RESET_USB_PHY BIT(4) + +#define AR933X_RESET_GE1_MDIO BIT(23) +#define AR933X_RESET_GE0_MDIO BIT(22) +#define AR933X_RESET_GE1_MAC BIT(13) +#define AR933X_RESET_WMAC BIT(11) +#define AR933X_RESET_GE0_MAC BIT(9) +#define AR933X_RESET_USB_HOST BIT(5) +#define AR933X_RESET_USB_PHY BIT(4) +#define AR933X_RESET_USBSUS_OVERRIDE BIT(3) + +#define AR934X_RESET_HOST BIT(31) +#define AR934X_RESET_SLIC BIT(30) +#define AR934X_RESET_HDMA BIT(29) +#define AR934X_RESET_EXTERNAL BIT(28) +#define AR934X_RESET_RTC BIT(27) +#define AR934X_RESET_PCIE_EP_INT BIT(26) +#define AR934X_RESET_CHKSUM_ACC BIT(25) +#define AR934X_RESET_FULL_CHIP BIT(24) +#define AR934X_RESET_GE1_MDIO BIT(23) +#define AR934X_RESET_GE0_MDIO BIT(22) +#define AR934X_RESET_CPU_NMI BIT(21) +#define AR934X_RESET_CPU_COLD BIT(20) +#define AR934X_RESET_HOST_RESET_INT BIT(19) +#define AR934X_RESET_PCIE_EP BIT(18) +#define AR934X_RESET_UART1 BIT(17) +#define AR934X_RESET_DDR BIT(16) +#define AR934X_RESET_USB_PHY_PLL_PWD_EXT BIT(15) +#define AR934X_RESET_NANDF BIT(14) +#define AR934X_RESET_GE1_MAC BIT(13) +#define AR934X_RESET_ETH_SWITCH_ANALOG BIT(12) +#define AR934X_RESET_USB_PHY_ANALOG BIT(11) +#define AR934X_RESET_HOST_DMA_INT BIT(10) +#define AR934X_RESET_GE0_MAC BIT(9) +#define AR934X_RESET_ETH_SWITCH BIT(8) +#define AR934X_RESET_PCIE_PHY BIT(7) +#define AR934X_RESET_PCIE BIT(6) +#define AR934X_RESET_USB_HOST BIT(5) +#define AR934X_RESET_USB_PHY BIT(4) +#define AR934X_RESET_USBSUS_OVERRIDE BIT(3) +#define AR934X_RESET_LUT BIT(2) +#define AR934X_RESET_MBOX BIT(1) +#define AR934X_RESET_I2S BIT(0) + +#define QCA953X_RESET_USB_EXT_PWR BIT(29) +#define QCA953X_RESET_EXTERNAL BIT(28) +#define QCA953X_RESET_RTC BIT(27) +#define QCA953X_RESET_FULL_CHIP BIT(24) +#define QCA953X_RESET_GE1_MDIO BIT(23) +#define QCA953X_RESET_GE0_MDIO BIT(22) +#define QCA953X_RESET_CPU_NMI BIT(21) +#define QCA953X_RESET_CPU_COLD BIT(20) +#define QCA953X_RESET_DDR BIT(16) +#define QCA953X_RESET_USB_PHY_PLL_PWD_EXT BIT(15) +#define QCA953X_RESET_GE1_MAC BIT(13) +#define QCA953X_RESET_ETH_SWITCH_ANALOG BIT(12) +#define QCA953X_RESET_USB_PHY_ANALOG BIT(11) +#define QCA953X_RESET_GE0_MAC BIT(9) +#define QCA953X_RESET_ETH_SWITCH BIT(8) +#define QCA953X_RESET_PCIE_PHY BIT(7) +#define QCA953X_RESET_PCIE BIT(6) +#define QCA953X_RESET_USB_HOST BIT(5) +#define QCA953X_RESET_USB_PHY BIT(4) +#define QCA953X_RESET_USBSUS_OVERRIDE BIT(3) + +#define QCA955X_RESET_HOST BIT(31) +#define QCA955X_RESET_SLIC BIT(30) +#define QCA955X_RESET_HDMA BIT(29) +#define QCA955X_RESET_EXTERNAL BIT(28) +#define QCA955X_RESET_RTC BIT(27) +#define QCA955X_RESET_PCIE_EP_INT BIT(26) +#define QCA955X_RESET_CHKSUM_ACC BIT(25) +#define QCA955X_RESET_FULL_CHIP BIT(24) +#define QCA955X_RESET_GE1_MDIO BIT(23) +#define QCA955X_RESET_GE0_MDIO BIT(22) +#define QCA955X_RESET_CPU_NMI BIT(21) +#define QCA955X_RESET_CPU_COLD BIT(20) +#define QCA955X_RESET_HOST_RESET_INT BIT(19) +#define QCA955X_RESET_PCIE_EP BIT(18) +#define QCA955X_RESET_UART1 BIT(17) +#define QCA955X_RESET_DDR BIT(16) +#define QCA955X_RESET_USB_PHY_PLL_PWD_EXT BIT(15) +#define QCA955X_RESET_NANDF BIT(14) +#define QCA955X_RESET_GE1_MAC BIT(13) +#define QCA955X_RESET_SGMII_ANALOG BIT(12) +#define QCA955X_RESET_USB_PHY_ANALOG BIT(11) +#define QCA955X_RESET_HOST_DMA_INT BIT(10) +#define QCA955X_RESET_GE0_MAC BIT(9) +#define QCA955X_RESET_SGMII BIT(8) +#define QCA955X_RESET_PCIE_PHY BIT(7) +#define QCA955X_RESET_PCIE BIT(6) +#define QCA955X_RESET_USB_HOST BIT(5) +#define QCA955X_RESET_USB_PHY BIT(4) +#define QCA955X_RESET_USBSUS_OVERRIDE BIT(3) +#define QCA955X_RESET_LUT BIT(2) +#define QCA955X_RESET_MBOX BIT(1) +#define QCA955X_RESET_I2S BIT(0) + +#define AR933X_BOOTSTRAP_MDIO_GPIO_EN BIT(18) +#define AR933X_BOOTSTRAP_DDR2 BIT(13) +#define AR933X_BOOTSTRAP_EEPBUSY BIT(4) +#define AR933X_BOOTSTRAP_REF_CLK_40 BIT(0) + +#define AR934X_BOOTSTRAP_SW_OPTION8 BIT(23) +#define AR934X_BOOTSTRAP_SW_OPTION7 BIT(22) +#define AR934X_BOOTSTRAP_SW_OPTION6 BIT(21) +#define AR934X_BOOTSTRAP_SW_OPTION5 BIT(20) +#define AR934X_BOOTSTRAP_SW_OPTION4 BIT(19) +#define AR934X_BOOTSTRAP_SW_OPTION3 BIT(18) +#define AR934X_BOOTSTRAP_SW_OPTION2 BIT(17) +#define AR934X_BOOTSTRAP_SW_OPTION1 BIT(16) +#define AR934X_BOOTSTRAP_USB_MODE_DEVICE BIT(7) +#define AR934X_BOOTSTRAP_PCIE_RC BIT(6) +#define AR934X_BOOTSTRAP_EJTAG_MODE BIT(5) +#define AR934X_BOOTSTRAP_REF_CLK_40 BIT(4) +#define AR934X_BOOTSTRAP_BOOT_FROM_SPI BIT(2) +#define AR934X_BOOTSTRAP_SDRAM_DISABLED BIT(1) +#define AR934X_BOOTSTRAP_DDR1 BIT(0) + +#define QCA953X_BOOTSTRAP_SW_OPTION2 BIT(12) +#define QCA953X_BOOTSTRAP_SW_OPTION1 BIT(11) +#define QCA953X_BOOTSTRAP_EJTAG_MODE BIT(5) +#define QCA953X_BOOTSTRAP_REF_CLK_40 BIT(4) +#define QCA953X_BOOTSTRAP_SDRAM_DISABLED BIT(1) +#define QCA953X_BOOTSTRAP_DDR1 BIT(0) + +#define QCA955X_BOOTSTRAP_REF_CLK_40 BIT(4) + +#define QCA956X_BOOTSTRAP_REF_CLK_40 BIT(2) + +#define AR934X_PCIE_WMAC_INT_WMAC_MISC BIT(0) +#define AR934X_PCIE_WMAC_INT_WMAC_TX BIT(1) +#define AR934X_PCIE_WMAC_INT_WMAC_RXLP BIT(2) +#define AR934X_PCIE_WMAC_INT_WMAC_RXHP BIT(3) +#define AR934X_PCIE_WMAC_INT_PCIE_RC BIT(4) +#define AR934X_PCIE_WMAC_INT_PCIE_RC0 BIT(5) +#define AR934X_PCIE_WMAC_INT_PCIE_RC1 BIT(6) +#define AR934X_PCIE_WMAC_INT_PCIE_RC2 BIT(7) +#define AR934X_PCIE_WMAC_INT_PCIE_RC3 BIT(8) +#define AR934X_PCIE_WMAC_INT_WMAC_ALL \ + (AR934X_PCIE_WMAC_INT_WMAC_MISC | AR934X_PCIE_WMAC_INT_WMAC_TX | \ + AR934X_PCIE_WMAC_INT_WMAC_RXLP | AR934X_PCIE_WMAC_INT_WMAC_RXHP) + +#define AR934X_PCIE_WMAC_INT_PCIE_ALL \ + (AR934X_PCIE_WMAC_INT_PCIE_RC | AR934X_PCIE_WMAC_INT_PCIE_RC0 | \ + AR934X_PCIE_WMAC_INT_PCIE_RC1 | AR934X_PCIE_WMAC_INT_PCIE_RC2 | \ + AR934X_PCIE_WMAC_INT_PCIE_RC3) + +#define QCA953X_PCIE_WMAC_INT_WMAC_MISC BIT(0) +#define QCA953X_PCIE_WMAC_INT_WMAC_TX BIT(1) +#define QCA953X_PCIE_WMAC_INT_WMAC_RXLP BIT(2) +#define QCA953X_PCIE_WMAC_INT_WMAC_RXHP BIT(3) +#define QCA953X_PCIE_WMAC_INT_PCIE_RC BIT(4) +#define QCA953X_PCIE_WMAC_INT_PCIE_RC0 BIT(5) +#define QCA953X_PCIE_WMAC_INT_PCIE_RC1 BIT(6) +#define QCA953X_PCIE_WMAC_INT_PCIE_RC2 BIT(7) +#define QCA953X_PCIE_WMAC_INT_PCIE_RC3 BIT(8) +#define QCA953X_PCIE_WMAC_INT_WMAC_ALL \ + (QCA953X_PCIE_WMAC_INT_WMAC_MISC | QCA953X_PCIE_WMAC_INT_WMAC_TX | \ + QCA953X_PCIE_WMAC_INT_WMAC_RXLP | QCA953X_PCIE_WMAC_INT_WMAC_RXHP) + +#define QCA953X_PCIE_WMAC_INT_PCIE_ALL \ + (QCA953X_PCIE_WMAC_INT_PCIE_RC | QCA953X_PCIE_WMAC_INT_PCIE_RC0 | \ + QCA953X_PCIE_WMAC_INT_PCIE_RC1 | QCA953X_PCIE_WMAC_INT_PCIE_RC2 | \ + QCA953X_PCIE_WMAC_INT_PCIE_RC3) + +#define QCA955X_EXT_INT_WMAC_MISC BIT(0) +#define QCA955X_EXT_INT_WMAC_TX BIT(1) +#define QCA955X_EXT_INT_WMAC_RXLP BIT(2) +#define QCA955X_EXT_INT_WMAC_RXHP BIT(3) +#define QCA955X_EXT_INT_PCIE_RC1 BIT(4) +#define QCA955X_EXT_INT_PCIE_RC1_INT0 BIT(5) +#define QCA955X_EXT_INT_PCIE_RC1_INT1 BIT(6) +#define QCA955X_EXT_INT_PCIE_RC1_INT2 BIT(7) +#define QCA955X_EXT_INT_PCIE_RC1_INT3 BIT(8) +#define QCA955X_EXT_INT_PCIE_RC2 BIT(12) +#define QCA955X_EXT_INT_PCIE_RC2_INT0 BIT(13) +#define QCA955X_EXT_INT_PCIE_RC2_INT1 BIT(14) +#define QCA955X_EXT_INT_PCIE_RC2_INT2 BIT(15) +#define QCA955X_EXT_INT_PCIE_RC2_INT3 BIT(16) +#define QCA955X_EXT_INT_USB1 BIT(24) +#define QCA955X_EXT_INT_USB2 BIT(28) + +#define QCA955X_EXT_INT_WMAC_ALL \ + (QCA955X_EXT_INT_WMAC_MISC | QCA955X_EXT_INT_WMAC_TX | \ + QCA955X_EXT_INT_WMAC_RXLP | QCA955X_EXT_INT_WMAC_RXHP) + +#define QCA955X_EXT_INT_PCIE_RC1_ALL \ + (QCA955X_EXT_INT_PCIE_RC1 | QCA955X_EXT_INT_PCIE_RC1_INT0 | \ + QCA955X_EXT_INT_PCIE_RC1_INT1 | QCA955X_EXT_INT_PCIE_RC1_INT2 | \ + QCA955X_EXT_INT_PCIE_RC1_INT3) + +#define QCA955X_EXT_INT_PCIE_RC2_ALL \ + (QCA955X_EXT_INT_PCIE_RC2 | QCA955X_EXT_INT_PCIE_RC2_INT0 | \ + QCA955X_EXT_INT_PCIE_RC2_INT1 | QCA955X_EXT_INT_PCIE_RC2_INT2 | \ + QCA955X_EXT_INT_PCIE_RC2_INT3) + +#define QCA956X_EXT_INT_WMAC_MISC BIT(0) +#define QCA956X_EXT_INT_WMAC_TX BIT(1) +#define QCA956X_EXT_INT_WMAC_RXLP BIT(2) +#define QCA956X_EXT_INT_WMAC_RXHP BIT(3) +#define QCA956X_EXT_INT_PCIE_RC1 BIT(4) +#define QCA956X_EXT_INT_PCIE_RC1_INT0 BIT(5) +#define QCA956X_EXT_INT_PCIE_RC1_INT1 BIT(6) +#define QCA956X_EXT_INT_PCIE_RC1_INT2 BIT(7) +#define QCA956X_EXT_INT_PCIE_RC1_INT3 BIT(8) +#define QCA956X_EXT_INT_PCIE_RC2 BIT(12) +#define QCA956X_EXT_INT_PCIE_RC2_INT0 BIT(13) +#define QCA956X_EXT_INT_PCIE_RC2_INT1 BIT(14) +#define QCA956X_EXT_INT_PCIE_RC2_INT2 BIT(15) +#define QCA956X_EXT_INT_PCIE_RC2_INT3 BIT(16) +#define QCA956X_EXT_INT_USB1 BIT(24) +#define QCA956X_EXT_INT_USB2 BIT(28) + +#define QCA956X_EXT_INT_WMAC_ALL \ + (QCA956X_EXT_INT_WMAC_MISC | QCA956X_EXT_INT_WMAC_TX | \ + QCA956X_EXT_INT_WMAC_RXLP | QCA956X_EXT_INT_WMAC_RXHP) + +#define QCA956X_EXT_INT_PCIE_RC1_ALL \ + (QCA956X_EXT_INT_PCIE_RC1 | QCA956X_EXT_INT_PCIE_RC1_INT0 | \ + QCA956X_EXT_INT_PCIE_RC1_INT1 | QCA956X_EXT_INT_PCIE_RC1_INT2 | \ + QCA956X_EXT_INT_PCIE_RC1_INT3) + +#define QCA956X_EXT_INT_PCIE_RC2_ALL \ + (QCA956X_EXT_INT_PCIE_RC2 | QCA956X_EXT_INT_PCIE_RC2_INT0 | \ + QCA956X_EXT_INT_PCIE_RC2_INT1 | QCA956X_EXT_INT_PCIE_RC2_INT2 | \ + QCA956X_EXT_INT_PCIE_RC2_INT3) + +#define REV_ID_MAJOR_MASK 0xfff0 +#define REV_ID_MAJOR_AR71XX 0x00a0 +#define REV_ID_MAJOR_AR913X 0x00b0 +#define REV_ID_MAJOR_AR7240 0x00c0 +#define REV_ID_MAJOR_AR7241 0x0100 +#define REV_ID_MAJOR_AR7242 0x1100 +#define REV_ID_MAJOR_AR9330 0x0110 +#define REV_ID_MAJOR_AR9331 0x1110 +#define REV_ID_MAJOR_AR9341 0x0120 +#define REV_ID_MAJOR_AR9342 0x1120 +#define REV_ID_MAJOR_AR9344 0x2120 +#define REV_ID_MAJOR_QCA9533 0x0140 +#define REV_ID_MAJOR_QCA9533_V2 0x0160 +#define REV_ID_MAJOR_QCA9556 0x0130 +#define REV_ID_MAJOR_QCA9558 0x1130 +#define REV_ID_MAJOR_TP9343 0x0150 +#define REV_ID_MAJOR_QCA9561 0x1150 + +#define AR71XX_REV_ID_MINOR_MASK 0x3 +#define AR71XX_REV_ID_MINOR_AR7130 0x0 +#define AR71XX_REV_ID_MINOR_AR7141 0x1 +#define AR71XX_REV_ID_MINOR_AR7161 0x2 +#define AR913X_REV_ID_MINOR_AR9130 0x0 +#define AR913X_REV_ID_MINOR_AR9132 0x1 + +#define AR71XX_REV_ID_REVISION_MASK 0x3 +#define AR71XX_REV_ID_REVISION_SHIFT 2 +#define AR71XX_REV_ID_REVISION2_MASK 0xf + +/* + * RTC block + */ +#define AR933X_RTC_REG_RESET 0x40 +#define AR933X_RTC_REG_STATUS 0x44 +#define AR933X_RTC_REG_DERIVED 0x48 +#define AR933X_RTC_REG_FORCE_WAKE 0x4c +#define AR933X_RTC_REG_INT_CAUSE 0x50 +#define AR933X_RTC_REG_CAUSE_CLR 0x50 +#define AR933X_RTC_REG_INT_ENABLE 0x54 +#define AR933X_RTC_REG_INT_MASKE 0x58 + +#define QCA953X_RTC_REG_SYNC_RESET 0x40 +#define QCA953X_RTC_REG_SYNC_STATUS 0x44 + +/* + * SPI block + */ +#define AR71XX_SPI_REG_FS 0x00 +#define AR71XX_SPI_REG_CTRL 0x04 +#define AR71XX_SPI_REG_IOC 0x08 +#define AR71XX_SPI_REG_RDS 0x0c + +#define AR71XX_SPI_FS_GPIO BIT(0) + +#define AR71XX_SPI_CTRL_RD BIT(6) +#define AR71XX_SPI_CTRL_DIV_MASK 0x3f + +#define AR71XX_SPI_IOC_DO BIT(0) +#define AR71XX_SPI_IOC_CLK BIT(8) +#define AR71XX_SPI_IOC_CS(n) BIT(16 + (n)) +#define AR71XX_SPI_IOC_CS0 AR71XX_SPI_IOC_CS(0) +#define AR71XX_SPI_IOC_CS1 AR71XX_SPI_IOC_CS(1) +#define AR71XX_SPI_IOC_CS2 AR71XX_SPI_IOC_CS(2) +#define AR71XX_SPI_IOC_CS_ALL \ + (AR71XX_SPI_IOC_CS0 | AR71XX_SPI_IOC_CS1 | AR71XX_SPI_IOC_CS2) + +/* + * GPIO block + */ +#define AR71XX_GPIO_REG_OE 0x00 +#define AR71XX_GPIO_REG_IN 0x04 +#define AR71XX_GPIO_REG_OUT 0x08 +#define AR71XX_GPIO_REG_SET 0x0c +#define AR71XX_GPIO_REG_CLEAR 0x10 +#define AR71XX_GPIO_REG_INT_MODE 0x14 +#define AR71XX_GPIO_REG_INT_TYPE 0x18 +#define AR71XX_GPIO_REG_INT_POLARITY 0x1c +#define AR71XX_GPIO_REG_INT_PENDING 0x20 +#define AR71XX_GPIO_REG_INT_ENABLE 0x24 +#define AR71XX_GPIO_REG_FUNC 0x28 +#define AR933X_GPIO_REG_FUNC 0x30 + +#define AR934X_GPIO_REG_OUT_FUNC0 0x2c +#define AR934X_GPIO_REG_OUT_FUNC1 0x30 +#define AR934X_GPIO_REG_OUT_FUNC2 0x34 +#define AR934X_GPIO_REG_OUT_FUNC3 0x38 +#define AR934X_GPIO_REG_OUT_FUNC4 0x3c +#define AR934X_GPIO_REG_OUT_FUNC5 0x40 +#define AR934X_GPIO_REG_FUNC 0x6c + +#define QCA953X_GPIO_REG_OUT_FUNC0 0x2c +#define QCA953X_GPIO_REG_OUT_FUNC1 0x30 +#define QCA953X_GPIO_REG_OUT_FUNC2 0x34 +#define QCA953X_GPIO_REG_OUT_FUNC3 0x38 +#define QCA953X_GPIO_REG_OUT_FUNC4 0x3c +#define QCA953X_GPIO_REG_IN_ENABLE0 0x44 +#define QCA953X_GPIO_REG_FUNC 0x6c + +#define QCA955X_GPIO_REG_OUT_FUNC0 0x2c +#define QCA955X_GPIO_REG_OUT_FUNC1 0x30 +#define QCA955X_GPIO_REG_OUT_FUNC2 0x34 +#define QCA955X_GPIO_REG_OUT_FUNC3 0x38 +#define QCA955X_GPIO_REG_OUT_FUNC4 0x3c +#define QCA955X_GPIO_REG_OUT_FUNC5 0x40 +#define QCA955X_GPIO_REG_FUNC 0x6c + +#define QCA956X_GPIO_REG_OUT_FUNC0 0x2c +#define QCA956X_GPIO_REG_OUT_FUNC1 0x30 +#define QCA956X_GPIO_REG_OUT_FUNC2 0x34 +#define QCA956X_GPIO_REG_OUT_FUNC3 0x38 +#define QCA956X_GPIO_REG_OUT_FUNC4 0x3c +#define QCA956X_GPIO_REG_OUT_FUNC5 0x40 +#define QCA956X_GPIO_REG_IN_ENABLE0 0x44 +#define QCA956X_GPIO_REG_IN_ENABLE3 0x50 +#define QCA956X_GPIO_REG_FUNC 0x6c + +#define AR71XX_GPIO_FUNC_STEREO_EN BIT(17) +#define AR71XX_GPIO_FUNC_SLIC_EN BIT(16) +#define AR71XX_GPIO_FUNC_SPI_CS2_EN BIT(13) +#define AR71XX_GPIO_FUNC_SPI_CS1_EN BIT(12) +#define AR71XX_GPIO_FUNC_UART_EN BIT(8) +#define AR71XX_GPIO_FUNC_USB_OC_EN BIT(4) +#define AR71XX_GPIO_FUNC_USB_CLK_EN BIT(0) + +#define AR724X_GPIO_FUNC_GE0_MII_CLK_EN BIT(19) +#define AR724X_GPIO_FUNC_SPI_EN BIT(18) +#define AR724X_GPIO_FUNC_SPI_CS_EN2 BIT(14) +#define AR724X_GPIO_FUNC_SPI_CS_EN1 BIT(13) +#define AR724X_GPIO_FUNC_CLK_OBS5_EN BIT(12) +#define AR724X_GPIO_FUNC_CLK_OBS4_EN BIT(11) +#define AR724X_GPIO_FUNC_CLK_OBS3_EN BIT(10) +#define AR724X_GPIO_FUNC_CLK_OBS2_EN BIT(9) +#define AR724X_GPIO_FUNC_CLK_OBS1_EN BIT(8) +#define AR724X_GPIO_FUNC_ETH_SWITCH_LED4_EN BIT(7) +#define AR724X_GPIO_FUNC_ETH_SWITCH_LED3_EN BIT(6) +#define AR724X_GPIO_FUNC_ETH_SWITCH_LED2_EN BIT(5) +#define AR724X_GPIO_FUNC_ETH_SWITCH_LED1_EN BIT(4) +#define AR724X_GPIO_FUNC_ETH_SWITCH_LED0_EN BIT(3) +#define AR724X_GPIO_FUNC_UART_RTS_CTS_EN BIT(2) +#define AR724X_GPIO_FUNC_UART_EN BIT(1) +#define AR724X_GPIO_FUNC_JTAG_DISABLE BIT(0) + +#define AR913X_GPIO_FUNC_WMAC_LED_EN BIT(22) +#define AR913X_GPIO_FUNC_EXP_PORT_CS_EN BIT(21) +#define AR913X_GPIO_FUNC_I2S_REFCLKEN BIT(20) +#define AR913X_GPIO_FUNC_I2S_MCKEN BIT(19) +#define AR913X_GPIO_FUNC_I2S1_EN BIT(18) +#define AR913X_GPIO_FUNC_I2S0_EN BIT(17) +#define AR913X_GPIO_FUNC_SLIC_EN BIT(16) +#define AR913X_GPIO_FUNC_UART_RTSCTS_EN BIT(9) +#define AR913X_GPIO_FUNC_UART_EN BIT(8) +#define AR913X_GPIO_FUNC_USB_CLK_EN BIT(4) + +#define AR933X_GPIO(x) BIT(x) +#define AR933X_GPIO_FUNC_SPDIF2TCK BIT(31) +#define AR933X_GPIO_FUNC_SPDIF_EN BIT(30) +#define AR933X_GPIO_FUNC_I2SO_22_18_EN BIT(29) +#define AR933X_GPIO_FUNC_I2S_MCK_EN BIT(27) +#define AR933X_GPIO_FUNC_I2SO_EN BIT(26) +#define AR933X_GPIO_FUNC_ETH_SWITCH_LED_DUPL BIT(25) +#define AR933X_GPIO_FUNC_ETH_SWITCH_LED_COLL BIT(24) +#define AR933X_GPIO_FUNC_ETH_SWITCH_LED_ACT BIT(23) +#define AR933X_GPIO_FUNC_SPI_EN BIT(18) +#define AR933X_GPIO_FUNC_RES_TRUE BIT(15) +#define AR933X_GPIO_FUNC_SPI_CS_EN2 BIT(14) +#define AR933X_GPIO_FUNC_SPI_CS_EN1 BIT(13) +#define AR933X_GPIO_FUNC_XLNA_EN BIT(12) +#define AR933X_GPIO_FUNC_ETH_SWITCH_LED4_EN BIT(7) +#define AR933X_GPIO_FUNC_ETH_SWITCH_LED3_EN BIT(6) +#define AR933X_GPIO_FUNC_ETH_SWITCH_LED2_EN BIT(5) +#define AR933X_GPIO_FUNC_ETH_SWITCH_LED1_EN BIT(4) +#define AR933X_GPIO_FUNC_ETH_SWITCH_LED0_EN BIT(3) +#define AR933X_GPIO_FUNC_UART_RTS_CTS_EN BIT(2) +#define AR933X_GPIO_FUNC_UART_EN BIT(1) +#define AR933X_GPIO_FUNC_JTAG_DISABLE BIT(0) + +#define AR934X_GPIO_FUNC_CLK_OBS7_EN BIT(9) +#define AR934X_GPIO_FUNC_CLK_OBS6_EN BIT(8) +#define AR934X_GPIO_FUNC_CLK_OBS5_EN BIT(7) +#define AR934X_GPIO_FUNC_CLK_OBS4_EN BIT(6) +#define AR934X_GPIO_FUNC_CLK_OBS3_EN BIT(5) +#define AR934X_GPIO_FUNC_CLK_OBS2_EN BIT(4) +#define AR934X_GPIO_FUNC_CLK_OBS1_EN BIT(3) +#define AR934X_GPIO_FUNC_CLK_OBS0_EN BIT(2) +#define AR934X_GPIO_FUNC_JTAG_DISABLE BIT(1) + +#define AR934X_GPIO_OUT_GPIO 0 +#define AR934X_GPIO_OUT_SPI_CS1 7 +#define AR934X_GPIO_OUT_LED_LINK0 41 +#define AR934X_GPIO_OUT_LED_LINK1 42 +#define AR934X_GPIO_OUT_LED_LINK2 43 +#define AR934X_GPIO_OUT_LED_LINK3 44 +#define AR934X_GPIO_OUT_LED_LINK4 45 +#define AR934X_GPIO_OUT_EXT_LNA0 46 +#define AR934X_GPIO_OUT_EXT_LNA1 47 + +#define QCA953X_GPIO(x) BIT(x) +#define QCA953X_GPIO_MUX_MASK(x) (0xff << (x)) +#define QCA953X_GPIO_OUT_MUX_SPI_CS1 10 +#define QCA953X_GPIO_OUT_MUX_SPI_CS2 11 +#define QCA953X_GPIO_OUT_MUX_SPI_CS0 9 +#define QCA953X_GPIO_OUT_MUX_SPI_CLK 8 +#define QCA953X_GPIO_OUT_MUX_SPI_MOSI 12 +#define QCA953X_GPIO_OUT_MUX_UART0_SOUT 22 +#define QCA953X_GPIO_OUT_MUX_LED_LINK1 41 +#define QCA953X_GPIO_OUT_MUX_LED_LINK2 42 +#define QCA953X_GPIO_OUT_MUX_LED_LINK3 43 +#define QCA953X_GPIO_OUT_MUX_LED_LINK4 44 +#define QCA953X_GPIO_OUT_MUX_LED_LINK5 45 + +#define QCA953X_GPIO_IN_MUX_UART0_SIN 9 +#define QCA953X_GPIO_IN_MUX_SPI_DATA_IN 8 + +#define QCA956X_GPIO_OUT_MUX_GE0_MDO 32 +#define QCA956X_GPIO_OUT_MUX_GE0_MDC 33 + +#define AR71XX_GPIO_COUNT 16 +#define AR7240_GPIO_COUNT 18 +#define AR7241_GPIO_COUNT 20 +#define AR913X_GPIO_COUNT 22 +#define AR933X_GPIO_COUNT 30 +#define AR934X_GPIO_COUNT 23 +#define QCA953X_GPIO_COUNT 18 +#define QCA955X_GPIO_COUNT 24 +#define QCA956X_GPIO_COUNT 23 + +/* + * SRIF block + */ +#define AR933X_SRIF_DDR_DPLL1_REG 0x240 +#define AR933X_SRIF_DDR_DPLL2_REG 0x244 +#define AR933X_SRIF_DDR_DPLL3_REG 0x248 +#define AR933X_SRIF_DDR_DPLL4_REG 0x24c + +#define AR934X_SRIF_CPU_DPLL1_REG 0x1c0 +#define AR934X_SRIF_CPU_DPLL2_REG 0x1c4 +#define AR934X_SRIF_CPU_DPLL3_REG 0x1c8 + +#define AR934X_SRIF_DDR_DPLL1_REG 0x240 +#define AR934X_SRIF_DDR_DPLL2_REG 0x244 +#define AR934X_SRIF_DDR_DPLL3_REG 0x248 + +#define AR934X_SRIF_DPLL1_REFDIV_SHIFT 27 +#define AR934X_SRIF_DPLL1_REFDIV_MASK 0x1f +#define AR934X_SRIF_DPLL1_NINT_SHIFT 18 +#define AR934X_SRIF_DPLL1_NINT_MASK 0x1ff +#define AR934X_SRIF_DPLL1_NFRAC_MASK 0x0003ffff + +#define AR934X_SRIF_DPLL2_LOCAL_PLL BIT(30) +#define AR934X_SRIF_DPLL2_OUTDIV_SHIFT 13 +#define AR934X_SRIF_DPLL2_OUTDIV_MASK 0x7 + +#define QCA953X_SRIF_BB_DPLL1_REG 0x180 +#define QCA953X_SRIF_BB_DPLL2_REG 0x184 +#define QCA953X_SRIF_BB_DPLL3_REG 0x188 + +#define QCA953X_SRIF_CPU_DPLL1_REG 0x1c0 +#define QCA953X_SRIF_CPU_DPLL2_REG 0x1c4 +#define QCA953X_SRIF_CPU_DPLL3_REG 0x1c8 + +#define QCA953X_SRIF_DDR_DPLL1_REG 0x240 +#define QCA953X_SRIF_DDR_DPLL2_REG 0x244 +#define QCA953X_SRIF_DDR_DPLL3_REG 0x248 + +#define QCA953X_SRIF_PCIE_DPLL1_REG 0xc00 +#define QCA953X_SRIF_PCIE_DPLL2_REG 0xc04 +#define QCA953X_SRIF_PCIE_DPLL3_REG 0xc08 + +#define QCA953X_SRIF_PMU1_REG 0xc40 +#define QCA953X_SRIF_PMU2_REG 0xc44 + +#define QCA953X_SRIF_DPLL1_REFDIV_SHIFT 27 +#define QCA953X_SRIF_DPLL1_REFDIV_MASK 0x1f + +#define QCA953X_SRIF_DPLL1_NINT_SHIFT 18 +#define QCA953X_SRIF_DPLL1_NINT_MASK 0x1ff +#define QCA953X_SRIF_DPLL1_NFRAC_MASK 0x0003ffff + +#define QCA953X_SRIF_DPLL2_LOCAL_PLL BIT(30) + +#define QCA953X_SRIF_DPLL2_KI_SHIFT 29 +#define QCA953X_SRIF_DPLL2_KI_MASK 0x3 + +#define QCA953X_SRIF_DPLL2_KD_SHIFT 25 +#define QCA953X_SRIF_DPLL2_KD_MASK 0xf + +#define QCA953X_SRIF_DPLL2_PWD BIT(22) + +#define QCA953X_SRIF_DPLL2_OUTDIV_SHIFT 13 +#define QCA953X_SRIF_DPLL2_OUTDIV_MASK 0x7 + +/* + * MII_CTRL block + */ +#define AR71XX_MII_REG_MII0_CTRL 0x00 +#define AR71XX_MII_REG_MII1_CTRL 0x04 + +#define AR71XX_MII_CTRL_IF_MASK 3 +#define AR71XX_MII_CTRL_SPEED_SHIFT 4 +#define AR71XX_MII_CTRL_SPEED_MASK 3 +#define AR71XX_MII_CTRL_SPEED_10 0 +#define AR71XX_MII_CTRL_SPEED_100 1 +#define AR71XX_MII_CTRL_SPEED_1000 2 + +#define AR71XX_MII0_CTRL_IF_GMII 0 +#define AR71XX_MII0_CTRL_IF_MII 1 +#define AR71XX_MII0_CTRL_IF_RGMII 2 +#define AR71XX_MII0_CTRL_IF_RMII 3 + +#define AR71XX_MII1_CTRL_IF_RGMII 0 +#define AR71XX_MII1_CTRL_IF_RMII 1 + +/* + * AR933X GMAC interface + */ +#define AR933X_GMAC_REG_ETH_CFG 0x00 + +#define AR933X_ETH_CFG_RGMII_GE0 BIT(0) +#define AR933X_ETH_CFG_MII_GE0 BIT(1) +#define AR933X_ETH_CFG_GMII_GE0 BIT(2) +#define AR933X_ETH_CFG_MII_GE0_MASTER BIT(3) +#define AR933X_ETH_CFG_MII_GE0_SLAVE BIT(4) +#define AR933X_ETH_CFG_MII_GE0_ERR_EN BIT(5) +#define AR933X_ETH_CFG_SW_PHY_SWAP BIT(7) +#define AR933X_ETH_CFG_SW_PHY_ADDR_SWAP BIT(8) +#define AR933X_ETH_CFG_RMII_GE0 BIT(9) +#define AR933X_ETH_CFG_RMII_GE0_SPD_10 0 +#define AR933X_ETH_CFG_RMII_GE0_SPD_100 BIT(10) + +/* + * AR934X GMAC Interface + */ +#define AR934X_GMAC_REG_ETH_CFG 0x00 + +#define AR934X_ETH_CFG_RGMII_GMAC0 BIT(0) +#define AR934X_ETH_CFG_MII_GMAC0 BIT(1) +#define AR934X_ETH_CFG_GMII_GMAC0 BIT(2) +#define AR934X_ETH_CFG_MII_GMAC0_MASTER BIT(3) +#define AR934X_ETH_CFG_MII_GMAC0_SLAVE BIT(4) +#define AR934X_ETH_CFG_MII_GMAC0_ERR_EN BIT(5) +#define AR934X_ETH_CFG_SW_ONLY_MODE BIT(6) +#define AR934X_ETH_CFG_SW_PHY_SWAP BIT(7) +#define AR934X_ETH_CFG_SW_APB_ACCESS BIT(9) +#define AR934X_ETH_CFG_RMII_GMAC0 BIT(10) +#define AR933X_ETH_CFG_MII_CNTL_SPEED BIT(11) +#define AR934X_ETH_CFG_RMII_GMAC0_MASTER BIT(12) +#define AR933X_ETH_CFG_SW_ACC_MSB_FIRST BIT(13) +#define AR934X_ETH_CFG_RXD_DELAY BIT(14) +#define AR934X_ETH_CFG_RXD_DELAY_MASK 0x3 +#define AR934X_ETH_CFG_RXD_DELAY_SHIFT 14 +#define AR934X_ETH_CFG_RDV_DELAY BIT(16) +#define AR934X_ETH_CFG_RDV_DELAY_MASK 0x3 +#define AR934X_ETH_CFG_RDV_DELAY_SHIFT 16 + +/* + * QCA953X GMAC Interface + */ +#define QCA953X_GMAC_REG_ETH_CFG 0x00 + +#define QCA953X_ETH_CFG_SW_ONLY_MODE BIT(6) +#define QCA953X_ETH_CFG_SW_PHY_SWAP BIT(7) +#define QCA953X_ETH_CFG_SW_APB_ACCESS BIT(9) +#define QCA953X_ETH_CFG_SW_ACC_MSB_FIRST BIT(13) + +/* + * QCA955X GMAC Interface + */ + +#define QCA955X_GMAC_REG_ETH_CFG 0x00 + +#define QCA955X_ETH_CFG_RGMII_EN BIT(0) +#define QCA955X_ETH_CFG_GE0_SGMII BIT(6) + +#endif /* __ASM_AR71XX_H */ diff --git a/arch/mips/mach-ath79/include/mach/ath79.h b/arch/mips/mach-ath79/include/mach/ath79.h new file mode 100644 index 0000000000..90d80b8bc8 --- /dev/null +++ b/arch/mips/mach-ath79/include/mach/ath79.h @@ -0,0 +1,143 @@ +/* + * Atheros AR71XX/AR724X/AR913X common definitions + * + * Copyright (C) 2015-2016 Wills Wang + * Copyright (C) 2008-2011 Gabor Juhos + * Copyright (C) 2008 Imre Kaloz + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef __ASM_MACH_ATH79_H +#define __ASM_MACH_ATH79_H + +#include + +DECLARE_GLOBAL_DATA_PTR; + +enum ath79_soc_type { + ATH79_SOC_UNKNOWN, + ATH79_SOC_AR7130, + ATH79_SOC_AR7141, + ATH79_SOC_AR7161, + ATH79_SOC_AR7240, + ATH79_SOC_AR7241, + ATH79_SOC_AR7242, + ATH79_SOC_AR9130, + ATH79_SOC_AR9132, + ATH79_SOC_AR9330, + ATH79_SOC_AR9331, + ATH79_SOC_AR9341, + ATH79_SOC_AR9342, + ATH79_SOC_AR9344, + ATH79_SOC_QCA9533, + ATH79_SOC_QCA9556, + ATH79_SOC_QCA9558, + ATH79_SOC_TP9343, + ATH79_SOC_QCA9561, +}; + +static inline int soc_is_ar71xx(void) +{ + return gd->arch.soc == ATH79_SOC_AR7130 || + gd->arch.soc == ATH79_SOC_AR7141 || + gd->arch.soc == ATH79_SOC_AR7161; +} + +static inline int soc_is_ar724x(void) +{ + return gd->arch.soc == ATH79_SOC_AR7240 || + gd->arch.soc == ATH79_SOC_AR7241 || + gd->arch.soc == ATH79_SOC_AR7242; +} + +static inline int soc_is_ar7240(void) +{ + return gd->arch.soc == ATH79_SOC_AR7240; +} + +static inline int soc_is_ar7241(void) +{ + return gd->arch.soc == ATH79_SOC_AR7241; +} + +static inline int soc_is_ar7242(void) +{ + return gd->arch.soc == ATH79_SOC_AR7242; +} + +static inline int soc_is_ar913x(void) +{ + return gd->arch.soc == ATH79_SOC_AR9130 || + gd->arch.soc == ATH79_SOC_AR9132; +} + +static inline int soc_is_ar933x(void) +{ + return gd->arch.soc == ATH79_SOC_AR9330 || + gd->arch.soc == ATH79_SOC_AR9331; +} + +static inline int soc_is_ar9341(void) +{ + return gd->arch.soc == ATH79_SOC_AR9341; +} + +static inline int soc_is_ar9342(void) +{ + return gd->arch.soc == ATH79_SOC_AR9342; +} + +static inline int soc_is_ar9344(void) +{ + return gd->arch.soc == ATH79_SOC_AR9344; +} + +static inline int soc_is_ar934x(void) +{ + return soc_is_ar9341() || + soc_is_ar9342() || + soc_is_ar9344(); +} + +static inline int soc_is_qca9533(void) +{ + return gd->arch.soc == ATH79_SOC_QCA9533; +} + +static inline int soc_is_qca953x(void) +{ + return soc_is_qca9533(); +} + +static inline int soc_is_qca9556(void) +{ + return gd->arch.soc == ATH79_SOC_QCA9556; +} + +static inline int soc_is_qca9558(void) +{ + return gd->arch.soc == ATH79_SOC_QCA9558; +} + +static inline int soc_is_qca955x(void) +{ + return soc_is_qca9556() || soc_is_qca9558(); +} + +static inline int soc_is_tp9343(void) +{ + return gd->arch.soc == ATH79_SOC_TP9343; +} + +static inline int soc_is_qca9561(void) +{ + return gd->arch.soc == ATH79_SOC_QCA9561; +} + +static inline int soc_is_qca956x(void) +{ + return soc_is_tp9343() || soc_is_qca9561(); +} + +#endif /* __ASM_MACH_ATH79_H */ diff --git a/arch/mips/mach-ath79/include/mach/ddr.h b/arch/mips/mach-ath79/include/mach/ddr.h new file mode 100644 index 0000000000..181179aebf --- /dev/null +++ b/arch/mips/mach-ath79/include/mach/ddr.h @@ -0,0 +1,13 @@ +/* + * Copyright (C) 2015-2016 Wills Wang + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef __ASM_MACH_DDR_H +#define __ASM_MACH_DDR_H + +void ddr_init(void); +void ddr_tap_tuning(void); + +#endif /* __ASM_MACH_DDR_H */ diff --git a/arch/mips/mach-ath79/include/mach/reset.h b/arch/mips/mach-ath79/include/mach/reset.h new file mode 100644 index 0000000000..c383bfe608 --- /dev/null +++ b/arch/mips/mach-ath79/include/mach/reset.h @@ -0,0 +1,14 @@ +/* + * Copyright (C) 2015-2016 Wills Wang + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef __ASM_MACH_RESET_H +#define __ASM_MACH_RESET_H + +#include + +u32 get_bootstrap(void); + +#endif /* __ASM_MACH_RESET_H */ diff --git a/arch/mips/mach-ath79/reset.c b/arch/mips/mach-ath79/reset.c new file mode 100644 index 0000000000..2ea2f8d3ac --- /dev/null +++ b/arch/mips/mach-ath79/reset.c @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2015-2016 Wills Wang + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include +#include +#include + +void _machine_restart(void) +{ + void __iomem *base; + u32 reg = 0; + + base = map_physmem(AR71XX_RESET_BASE, AR71XX_RESET_SIZE, + MAP_NOCACHE); + if (soc_is_ar71xx()) + reg = AR71XX_RESET_REG_RESET_MODULE; + else if (soc_is_ar724x()) + reg = AR724X_RESET_REG_RESET_MODULE; + else if (soc_is_ar913x()) + reg = AR913X_RESET_REG_RESET_MODULE; + else if (soc_is_ar933x()) + reg = AR933X_RESET_REG_RESET_MODULE; + else if (soc_is_ar934x()) + reg = AR934X_RESET_REG_RESET_MODULE; + else if (soc_is_qca953x()) + reg = QCA953X_RESET_REG_RESET_MODULE; + else if (soc_is_qca955x()) + reg = QCA955X_RESET_REG_RESET_MODULE; + else if (soc_is_qca956x()) + reg = QCA956X_RESET_REG_RESET_MODULE; + else + puts("Reset register not defined for this SOC\n"); + + if (reg) + setbits_be32(base + reg, AR71XX_RESET_FULL_CHIP); + + while (1) + /* NOP */; +} + +u32 get_bootstrap(void) +{ + const void __iomem *base; + u32 reg = 0; + + base = map_physmem(AR71XX_RESET_BASE, AR71XX_RESET_SIZE, + MAP_NOCACHE); + if (soc_is_ar933x()) + reg = AR933X_RESET_REG_BOOTSTRAP; + else if (soc_is_ar934x()) + reg = AR934X_RESET_REG_BOOTSTRAP; + else if (soc_is_qca953x()) + reg = QCA953X_RESET_REG_BOOTSTRAP; + else if (soc_is_qca955x()) + reg = QCA955X_RESET_REG_BOOTSTRAP; + else if (soc_is_qca956x()) + reg = QCA956X_RESET_REG_BOOTSTRAP; + else + puts("Bootstrap register not defined for this SOC\n"); + + if (reg) + return readl(base + reg); + + return 0; +} From ee7bb5be35af71df46733b0b3f3e8c96b7b4066d Mon Sep 17 00:00:00 2001 From: Wills Wang Date: Wed, 16 Mar 2016 16:59:53 +0800 Subject: [PATCH 121/162] mips: ath79: add support for AR933x SOCs This patch enable work for ar933x SOC. Signed-off-by: Wills Wang --- arch/mips/mach-ath79/Kconfig | 9 + arch/mips/mach-ath79/Makefile | 2 + arch/mips/mach-ath79/ar933x/Makefile | 7 + arch/mips/mach-ath79/ar933x/clk.c | 89 ++++++ arch/mips/mach-ath79/ar933x/ddr.c | 333 ++++++++++++++++++++ arch/mips/mach-ath79/ar933x/lowlevel_init.S | 280 ++++++++++++++++ 6 files changed, 720 insertions(+) create mode 100644 arch/mips/mach-ath79/ar933x/Makefile create mode 100644 arch/mips/mach-ath79/ar933x/clk.c create mode 100644 arch/mips/mach-ath79/ar933x/ddr.c create mode 100644 arch/mips/mach-ath79/ar933x/lowlevel_init.S diff --git a/arch/mips/mach-ath79/Kconfig b/arch/mips/mach-ath79/Kconfig index 7d8ce098be..ab93d92b95 100644 --- a/arch/mips/mach-ath79/Kconfig +++ b/arch/mips/mach-ath79/Kconfig @@ -4,4 +4,13 @@ menu "QCA/Atheros 7xxx/9xxx platforms" config SYS_SOC default "ath79" +config SOC_AR933X + bool + select SUPPORTS_BIG_ENDIAN + select SUPPORTS_CPU_MIPS32_R1 + select SUPPORTS_CPU_MIPS32_R2 + select MIPS_TUNE_24KC + help + This supports QCA/Atheros ar933x family SOCs. + endmenu diff --git a/arch/mips/mach-ath79/Makefile b/arch/mips/mach-ath79/Makefile index 6203cf0242..9b9447e207 100644 --- a/arch/mips/mach-ath79/Makefile +++ b/arch/mips/mach-ath79/Makefile @@ -5,3 +5,5 @@ obj-y += reset.o obj-y += cpu.o obj-y += dram.o + +obj-$(CONFIG_SOC_AR933X) += ar933x/ \ No newline at end of file diff --git a/arch/mips/mach-ath79/ar933x/Makefile b/arch/mips/mach-ath79/ar933x/Makefile new file mode 100644 index 0000000000..fd74f0c2ae --- /dev/null +++ b/arch/mips/mach-ath79/ar933x/Makefile @@ -0,0 +1,7 @@ +# +# SPDX-License-Identifier: GPL-2.0+ +# + +obj-y += clk.o +obj-y += ddr.o +obj-y += lowlevel_init.o diff --git a/arch/mips/mach-ath79/ar933x/clk.c b/arch/mips/mach-ath79/ar933x/clk.c new file mode 100644 index 0000000000..9fcd4961f5 --- /dev/null +++ b/arch/mips/mach-ath79/ar933x/clk.c @@ -0,0 +1,89 @@ +/* + * Copyright (C) 2015-2016 Wills Wang + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include +#include +#include + +DECLARE_GLOBAL_DATA_PTR; + +static u32 ar933x_get_xtal(void) +{ + u32 val; + + val = get_bootstrap(); + if (val & AR933X_BOOTSTRAP_REF_CLK_40) + return 40000000; + else + return 25000000; +} + +int get_serial_clock(void) +{ + return ar933x_get_xtal(); +} + +int get_clocks(void) +{ + void __iomem *regs; + u32 val, xtal, pll, div; + + regs = map_physmem(AR71XX_PLL_BASE, AR71XX_PLL_SIZE, + MAP_NOCACHE); + xtal = ar933x_get_xtal(); + val = readl(regs + AR933X_PLL_CPU_CONFIG_REG); + + /* VCOOUT = XTAL * DIV_INT */ + div = (val >> AR933X_PLL_CPU_CONFIG_REFDIV_SHIFT) + & AR933X_PLL_CPU_CONFIG_REFDIV_MASK; + pll = xtal / div; + + /* PLLOUT = VCOOUT * (1/2^OUTDIV) */ + div = (val >> AR933X_PLL_CPU_CONFIG_NINT_SHIFT) + & AR933X_PLL_CPU_CONFIG_NINT_MASK; + pll *= div; + div = (val >> AR933X_PLL_CPU_CONFIG_OUTDIV_SHIFT) + & AR933X_PLL_CPU_CONFIG_OUTDIV_MASK; + if (!div) + div = 1; + pll >>= div; + + val = readl(regs + AR933X_PLL_CLK_CTRL_REG); + + /* CPU_CLK = PLLOUT / CPU_POST_DIV */ + div = ((val >> AR933X_PLL_CLK_CTRL_CPU_POST_DIV_SHIFT) + & AR933X_PLL_CLK_CTRL_CPU_POST_DIV_MASK) + 1; + gd->cpu_clk = pll / div; + + /* DDR_CLK = PLLOUT / DDR_POST_DIV */ + div = ((val >> AR933X_PLL_CLK_CTRL_DDR_POST_DIV_SHIFT) + & AR933X_PLL_CLK_CTRL_DDR_POST_DIV_MASK) + 1; + gd->mem_clk = pll / div; + + /* AHB_CLK = PLLOUT / AHB_POST_DIV */ + div = ((val >> AR933X_PLL_CLK_CTRL_AHB_POST_DIV_SHIFT) + & AR933X_PLL_CLK_CTRL_AHB_POST_DIV_MASK) + 1; + gd->bus_clk = pll / div; + + return 0; +} + +ulong get_bus_freq(ulong dummy) +{ + if (!gd->bus_clk) + get_clocks(); + return gd->bus_clk; +} + +ulong get_ddr_freq(ulong dummy) +{ + if (!gd->mem_clk) + get_clocks(); + return gd->mem_clk; +} diff --git a/arch/mips/mach-ath79/ar933x/ddr.c b/arch/mips/mach-ath79/ar933x/ddr.c new file mode 100644 index 0000000000..74e8e80ea7 --- /dev/null +++ b/arch/mips/mach-ath79/ar933x/ddr.c @@ -0,0 +1,333 @@ +/* + * Copyright (C) 2015-2016 Wills Wang + * Based on Atheros LSDK/QSDK + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include +#include +#include + +DECLARE_GLOBAL_DATA_PTR; + +#define DDR_CTRL_UPD_EMR3S BIT(5) +#define DDR_CTRL_UPD_EMR2S BIT(4) +#define DDR_CTRL_PRECHARGE BIT(3) +#define DDR_CTRL_AUTO_REFRESH BIT(2) +#define DDR_CTRL_UPD_EMRS BIT(1) +#define DDR_CTRL_UPD_MRS BIT(0) + +#define DDR_REFRESH_EN (1 << 14) +#define DDR_REFRESH_M 0x3ff +#define DDR_REFRESH(x) ((x) & 0x3ff) +#define DDR_REFRESH_VAL_25M (DDR_REFRESH_EN | DDR_REFRESH(390)) +#define DDR_REFRESH_VAL_40M (DDR_REFRESH_EN | DDR_REFRESH(624)) + +#define DDR_TRAS_S 0 +#define DDR_TRAS_M 0x1f +#define DDR_TRAS(x) ((x) << DDR_TRAS_S) +#define DDR_TRCD_M 0xf +#define DDR_TRCD_S 5 +#define DDR_TRCD(x) ((x) << DDR_TRCD_S) +#define DDR_TRP_M 0xf +#define DDR_TRP_S 9 +#define DDR_TRP(x) ((x) << DDR_TRP_S) +#define DDR_TRRD_M 0xf +#define DDR_TRRD_S 13 +#define DDR_TRRD(x) ((x) << DDR_TRRD_S) +#define DDR_TRFC_M 0x7f +#define DDR_TRFC_S 17 +#define DDR_TRFC(x) ((x) << DDR_TRFC_S) +#define DDR_TMRD_M 0xf +#define DDR_TMRD_S 23 +#define DDR_TMRD(x) ((x) << DDR_TMRD_S) +#define DDR_CAS_L_M 0x17 +#define DDR_CAS_L_S 27 +#define DDR_CAS_L(x) (((x) & DDR_CAS_L_M) << DDR_CAS_L_S) +#define DDR_OPEN (1 << 30) +#define DDR_CONF_REG_VAL (DDR_TRAS(16) | DDR_TRCD(6) | \ + DDR_TRP(6) | DDR_TRRD(4) | \ + DDR_TRFC(30) | DDR_TMRD(15) | \ + DDR_CAS_L(7) | DDR_OPEN) + +#define DDR_BURST_LEN_S 0 +#define DDR_BURST_LEN_M 0xf +#define DDR_BURST_LEN(x) ((x) << DDR_BURST_LEN_S) +#define DDR_BURST_TYPE (1 << 4) +#define DDR_CNTL_OE_EN (1 << 5) +#define DDR_PHASE_SEL (1 << 6) +#define DDR_CKE (1 << 7) +#define DDR_TWR_S 8 +#define DDR_TWR_M 0xf +#define DDR_TWR(x) ((x) << DDR_TWR_S) +#define DDR_TRTW_S 12 +#define DDR_TRTW_M 0x1f +#define DDR_TRTW(x) ((x) << DDR_TRTW_S) +#define DDR_TRTP_S 17 +#define DDR_TRTP_M 0xf +#define DDR_TRTP(x) ((x) << DDR_TRTP_S) +#define DDR_TWTR_S 21 +#define DDR_TWTR_M 0x1f +#define DDR_TWTR(x) ((x) << DDR_TWTR_S) +#define DDR_G_OPEN_L_S 26 +#define DDR_G_OPEN_L_M 0xf +#define DDR_G_OPEN_L(x) ((x) << DDR_G_OPEN_L_S) +#define DDR_HALF_WIDTH_LOW (1 << 31) +#define DDR_CONF2_REG_VAL (DDR_BURST_LEN(8) | DDR_CNTL_OE_EN | \ + DDR_CKE | DDR_TWR(6) | DDR_TRTW(14) | \ + DDR_TRTP(8) | DDR_TWTR(14) | \ + DDR_G_OPEN_L(7) | DDR_HALF_WIDTH_LOW) + +#define DDR2_CONF_TWL_S 10 +#define DDR2_CONF_TWL_M 0xf +#define DDR2_CONF_TWL(x) (((x) & DDR2_CONF_TWL_M) << DDR2_CONF_TWL_S) +#define DDR2_CONF_ODT BIT(9) +#define DDR2_CONF_TFAW_S 2 +#define DDR2_CONF_TFAW_M 0x3f +#define DDR2_CONF_TFAW(x) (((x) & DDR2_CONF_TFAW_M) << DDR2_CONF_TFAW_S) +#define DDR2_CONF_EN BIT(0) +#define DDR2_CONF_VAL (DDR2_CONF_TWL(2) | DDR2_CONF_ODT | \ + DDR2_CONF_TFAW(22) | DDR2_CONF_EN) + +#define DDR1_EXT_MODE_VAL 0x02 +#define DDR2_EXT_MODE_VAL 0x402 +#define DDR2_EXT_MODE_OCD_VAL 0x382 +#define DDR1_MODE_DLL_VAL 0x133 +#define DDR2_MODE_DLL_VAL 0x100 +#define DDR1_MODE_VAL 0x33 +#define DDR2_MODE_VAL 0xa33 +#define DDR_TAP_VAL0 0x08 +#define DDR_TAP_VAL1 0x09 + +void ddr_init(void) +{ + void __iomem *regs; + u32 val; + + regs = map_physmem(AR71XX_DDR_CTRL_BASE, AR71XX_DDR_CTRL_SIZE, + MAP_NOCACHE); + + writel(DDR_CONF_REG_VAL, regs + AR71XX_DDR_REG_CONFIG); + writel(DDR_CONF2_REG_VAL, regs + AR71XX_DDR_REG_CONFIG2); + + val = get_bootstrap(); + if (val & AR933X_BOOTSTRAP_DDR2) { + /* AHB maximum timeout */ + writel(0xfffff, regs + AR933X_DDR_REG_TIMEOUT_MAX); + + /* Enable DDR2 */ + writel(DDR2_CONF_VAL, regs + AR933X_DDR_REG_DDR2_CONFIG); + + /* Precharge All */ + writel(DDR_CTRL_PRECHARGE, regs + AR71XX_DDR_REG_CONTROL); + + /* Disable High Temperature Self-Refresh, Full Array */ + writel(0x00, regs + AR933X_DDR_REG_EMR2); + + /* Extended Mode Register 2 Set (EMR2S) */ + writel(DDR_CTRL_UPD_EMR2S, regs + AR71XX_DDR_REG_CONTROL); + + writel(0x00, regs + AR933X_DDR_REG_EMR3); + + /* Extended Mode Register 3 Set (EMR3S) */ + writel(DDR_CTRL_UPD_EMR3S, regs + AR71XX_DDR_REG_CONTROL); + + /* Enable DLL, Full strength, ODT Disabled */ + writel(0x00, regs + AR71XX_DDR_REG_EMR); + + /* Extended Mode Register Set (EMRS) */ + writel(DDR_CTRL_UPD_EMRS, regs + AR71XX_DDR_REG_CONTROL); + + /* Reset DLL */ + writel(DDR2_MODE_DLL_VAL, regs + AR71XX_DDR_REG_MODE); + + /* Mode Register Set (MRS) */ + writel(DDR_CTRL_UPD_MRS, regs + AR71XX_DDR_REG_CONTROL); + + /* Precharge All */ + writel(DDR_CTRL_PRECHARGE, regs + AR71XX_DDR_REG_CONTROL); + + /* Auto Refresh */ + writel(DDR_CTRL_AUTO_REFRESH, regs + AR71XX_DDR_REG_CONTROL); + writel(DDR_CTRL_AUTO_REFRESH, regs + AR71XX_DDR_REG_CONTROL); + + /* Write recovery (WR) 6 clock, CAS Latency 3, Burst Length 8 */ + writel(DDR2_MODE_VAL, regs + AR71XX_DDR_REG_MODE); + /* Mode Register Set (MRS) */ + writel(DDR_CTRL_UPD_MRS, regs + AR71XX_DDR_REG_CONTROL); + + /* Enable OCD defaults, Enable DLL, Reduced Drive Strength */ + writel(DDR2_EXT_MODE_OCD_VAL, regs + AR71XX_DDR_REG_EMR); + + /* Extended Mode Register Set (EMRS) */ + writel(DDR_CTRL_UPD_EMRS, regs + AR71XX_DDR_REG_CONTROL); + + /* OCD exit, Enable DLL, Enable /DQS, Reduced Drive Strength */ + writel(DDR2_EXT_MODE_VAL, regs + AR71XX_DDR_REG_EMR); + /* Extended Mode Register Set (EMRS) */ + writel(DDR_CTRL_UPD_EMRS, regs + AR71XX_DDR_REG_CONTROL); + + /* Refresh time control */ + if (val & AR933X_BOOTSTRAP_REF_CLK_40) + writel(DDR_REFRESH_VAL_40M, regs + + AR71XX_DDR_REG_REFRESH); + else + writel(DDR_REFRESH_VAL_25M, regs + + AR71XX_DDR_REG_REFRESH); + + /* DQS 0 Tap Control */ + writel(DDR_TAP_VAL0, regs + AR71XX_DDR_REG_TAP_CTRL0); + + /* DQS 1 Tap Control */ + writel(DDR_TAP_VAL1, regs + AR71XX_DDR_REG_TAP_CTRL1); + + /* For 16-bit DDR */ + writel(0xff, regs + AR71XX_DDR_REG_RD_CYCLE); + } else { + /* AHB maximum timeout */ + writel(0xfffff, regs + AR933X_DDR_REG_TIMEOUT_MAX); + + /* Precharge All */ + writel(DDR_CTRL_PRECHARGE, regs + AR71XX_DDR_REG_CONTROL); + + /* Reset DLL, Burst Length 8, CAS Latency 3 */ + writel(DDR1_MODE_DLL_VAL, regs + AR71XX_DDR_REG_MODE); + + /* Forces an MRS update cycle in DDR */ + writel(DDR_CTRL_UPD_MRS, regs + AR71XX_DDR_REG_CONTROL); + + /* Enable DLL, Full strength */ + writel(DDR1_EXT_MODE_VAL, regs + AR71XX_DDR_REG_EMR); + + /* Extended Mode Register Set (EMRS) */ + writel(DDR_CTRL_UPD_EMRS, regs + AR71XX_DDR_REG_CONTROL); + + /* Precharge All */ + writel(DDR_CTRL_PRECHARGE, regs + AR71XX_DDR_REG_CONTROL); + + /* Normal DLL, Burst Length 8, CAS Latency 3 */ + writel(DDR1_MODE_VAL, regs + AR71XX_DDR_REG_MODE); + + /* Mode Register Set (MRS) */ + writel(DDR_CTRL_UPD_MRS, regs + AR71XX_DDR_REG_CONTROL); + + /* Refresh time control */ + if (val & AR933X_BOOTSTRAP_REF_CLK_40) + writel(DDR_REFRESH_VAL_40M, regs + + AR71XX_DDR_REG_REFRESH); + else + writel(DDR_REFRESH_VAL_25M, regs + + AR71XX_DDR_REG_REFRESH); + + /* DQS 0 Tap Control */ + writel(DDR_TAP_VAL0, regs + AR71XX_DDR_REG_TAP_CTRL0); + + /* DQS 1 Tap Control */ + writel(DDR_TAP_VAL1, regs + AR71XX_DDR_REG_TAP_CTRL1); + + /* For 16-bit DDR */ + writel(0xff, regs + AR71XX_DDR_REG_RD_CYCLE); + } +} + +void ddr_tap_tuning(void) +{ + void __iomem *regs; + u32 *addr_k0, *addr_k1, *addr; + u32 val, tap, upper, lower; + int i, j, dir, err, done; + + regs = map_physmem(AR71XX_DDR_CTRL_BASE, AR71XX_DDR_CTRL_SIZE, + MAP_NOCACHE); + + /* Init memory pattern */ + addr = (void *)CKSEG0ADDR(0x2000); + for (i = 0; i < 256; i++) { + val = 0; + for (j = 0; j < 8; j++) { + if (i & (1 << j)) { + if (j % 2) + val |= 0xffff0000; + else + val |= 0x0000ffff; + } + + if (j % 2) { + *addr++ = val; + val = 0; + } + } + } + + err = 0; + done = 0; + dir = 1; + tap = readl(regs + AR71XX_DDR_REG_TAP_CTRL0); + val = tap; + while (!done) { + err = 0; + + /* Update new DDR tap value */ + writel(val, regs + AR71XX_DDR_REG_TAP_CTRL0); + writel(val, regs + AR71XX_DDR_REG_TAP_CTRL1); + + /* Compare DDR with cache */ + for (i = 0; i < 2; i++) { + addr_k1 = (void *)CKSEG1ADDR(0x2000); + addr_k0 = (void *)CKSEG0ADDR(0x2000); + addr = (void *)CKSEG0ADDR(0x3000); + + while (addr_k0 < addr) { + if (*addr_k1++ != *addr_k0++) { + err = 1; + break; + } + } + + if (err) + break; + } + + if (err) { + /* Save upper/lower threshold if error */ + if (dir) { + dir = 0; + val--; + upper = val; + val = tap; + } else { + val++; + lower = val; + done = 1; + } + } else { + /* Try the next value until limitation */ + if (dir) { + if (val < 0x20) { + val++; + } else { + dir = 0; + upper = val; + val = tap; + } + } else { + if (!val) { + lower = val; + done = 1; + } else { + val--; + } + } + } + } + + /* compute an intermediate value and write back */ + val = (upper + lower) / 2; + writel(val, regs + AR71XX_DDR_REG_TAP_CTRL0); + val++; + writel(val, regs + AR71XX_DDR_REG_TAP_CTRL1); +} diff --git a/arch/mips/mach-ath79/ar933x/lowlevel_init.S b/arch/mips/mach-ath79/ar933x/lowlevel_init.S new file mode 100644 index 0000000000..1b847f5eae --- /dev/null +++ b/arch/mips/mach-ath79/ar933x/lowlevel_init.S @@ -0,0 +1,280 @@ +/* + * Copyright (C) 2015-2016 Wills Wang + * Based on Atheros LSDK/QSDK and u-boot_mod project + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include +#include +#include + +#define SET_BIT(val, bit) ((val) | (1 << (bit))) +#define SET_PLL_PD(val) SET_BIT(val, 30) +#define AHB_DIV_TO_4(val) SET_BIT(SET_BIT(val, 15), 16) +#define PLL_BYPASS(val) SET_BIT(val, 2) + +#define MK_PLL_CONF(divint, refdiv, range, outdiv) \ + (((0x3F & divint) << 10) | \ + ((0x1F & refdiv) << 16) | \ + ((0x1 & range) << 21) | \ + ((0x7 & outdiv) << 23) ) + +#define MK_CLK_CNTL(cpudiv, ddrdiv, ahbdiv) \ + (((0x3 & (cpudiv - 1)) << 5) | \ + ((0x3 & (ddrdiv - 1)) << 10) | \ + ((0x3 & (ahbdiv - 1)) << 15) ) + +/* + * PLL_CPU_CONFIG_VAL + * + * Bit30 is set (CPU_PLLPWD = 1 -> power down control for CPU PLL) + * After PLL configuration we need to clear this bit + * + * Values written into CPU PLL Configuration (CPU_PLL_CONFIG) + * + * bits 10..15 (6bit) DIV_INT (Integer part of the DIV to CPU PLL) + * => 32 (0x20) VCOOUT = XTAL * DIV_INT + * bits 16..20 (5bit) REFDIV (Reference clock divider) + * => 1 (0x1) [Must start at values 1] + * bits 21 (1bit) RANGE (VCO frequency range of the CPU PLL) + * => 0 (0x0) [Doesn't impact clock values] + * bits 23..25 (3bit) OUTDIV (Ratio between VCO and PLL output) + * => 1 (0x1) [0 is illegal!] + * PLLOUT = VCOOUT * (1/2^OUTDIV) + */ +/* DIV_INT=32 (25MHz*32/2=400MHz), REFDIV=1, RANGE=0, OUTDIV=1 */ +#define PLL_CPU_CONFIG_VAL_40M MK_PLL_CONF(20, 1, 0, 1) +/* DIV_INT=20 (40MHz*20/2=400MHz), REFDIV=1, RANGE=0, OUTDIV=1 */ +#define PLL_CPU_CONFIG_VAL_25M MK_PLL_CONF(32, 1, 0, 1) + +/* + * PLL_CLK_CONTROL_VAL + * + * In PLL_CLK_CONTROL_VAL bit 2 is set (BYPASS = 1 -> bypass PLL) + * After PLL configuration we need to clear this bit + * + * Values written into CPU Clock Control Register CLOCK_CONTROL + * + * bits 2 (1bit) BYPASS (Bypass PLL. This defaults to 1 for test. + * Software must enable the CPU PLL for normal and + * then set this bit to 0) + * bits 5..6 (2bit) CPU_POST_DIV => 0 (DEFAULT, Ratio = 1) + * CPU_CLK = PLLOUT / CPU_POST_DIV + * bits 10..11 (2bit) DDR_POST_DIV => 0 (DEFAULT, Ratio = 1) + * DDR_CLK = PLLOUT / DDR_POST_DIV + * bits 15..16 (2bit) AHB_POST_DIV => 1 (DEFAULT, Ratio = 2) + * AHB_CLK = PLLOUT / AHB_POST_DIV + * + */ +#define PLL_CLK_CONTROL_VAL MK_CLK_CNTL(1, 1, 2) + + .text + .set noreorder + +LEAF(lowlevel_init) + /* These three WLAN_RESET will avoid original issue */ + li t3, 0x03 +1: + li t0, CKSEG1ADDR(AR71XX_RESET_BASE) + lw t1, AR933X_RESET_REG_RESET_MODULE(t0) + ori t1, t1, 0x0800 + sw t1, AR933X_RESET_REG_RESET_MODULE(t0) + nop + lw t1, AR933X_RESET_REG_RESET_MODULE(t0) + li t2, 0xfffff7ff + and t1, t1, t2 + sw t1, AR933X_RESET_REG_RESET_MODULE(t0) + nop + addi t3, t3, -1 + bnez t3, 1b + nop + + li t2, 0x20 +2: + beqz t2, 1b + nop + addi t2, t2, -1 + lw t5, AR933X_RESET_REG_BOOTSTRAP(t0) + andi t1, t5, 0x10 + bnez t1, 2b + nop + + li t1, 0x02110E + sw t1, AR933X_RESET_REG_BOOTSTRAP(t0) + nop + + /* RTC Force Wake */ + li t0, CKSEG1ADDR(AR933X_RTC_BASE) + li t1, 0x03 + sw t1, AR933X_RTC_REG_FORCE_WAKE(t0) + nop + nop + + /* RTC Reset */ + li t1, 0x00 + sw t1, AR933X_RTC_REG_RESET(t0) + nop + nop + + li t1, 0x01 + sw t1, AR933X_RTC_REG_RESET(t0) + nop + nop + + /* Wait for RTC in on state */ +1: + lw t1, AR933X_RTC_REG_STATUS(t0) + andi t1, t1, 0x02 + beqz t1, 1b + nop + + /* Program ki/kd */ + li t0, CKSEG1ADDR(AR933X_SRIF_BASE) + andi t1, t5, 0x01 # t5 BOOT_STRAP + bnez t1, 1f + nop + li t1, 0x19e82f01 + b 2f + nop +1: + li t1, 0x18e82f01 +2: + sw t1, AR933X_SRIF_DDR_DPLL2_REG(t0) + + /* Program phase shift */ + lw t1, AR933X_SRIF_DDR_DPLL3_REG(t0) + li t2, 0xc07fffff + and t1, t1, t2 + li t2, 0x800000 + or t1, t1, t2 + sw t1, AR933X_SRIF_DDR_DPLL3_REG(t0) + nop + + /* in some cases, the SoC doesn't start with higher clock on AHB */ + li t0, CKSEG1ADDR(AR71XX_PLL_BASE) + li t1, AHB_DIV_TO_4(PLL_BYPASS(PLL_CLK_CONTROL_VAL)) + sw t1, AR933X_PLL_CLK_CTRL_REG(t0) + nop + + /* Set SETTLE_TIME in CPU PLL */ + andi t1, t5, 0x01 # t5 BOOT_STRAP + bnez t1, 1f + nop + li t1, 0x0352 + b 2f + nop +1: + li t1, 0x0550 +2: + sw t1, AR71XX_PLL_REG_SEC_CONFIG(t0) + nop + + /* Set nint, frac, refdiv, outdiv, range according to xtal */ +0: + andi t1, t5, 0x01 # t5 BOOT_STRAP + bnez t1, 1f + nop + li t1, SET_PLL_PD(PLL_CPU_CONFIG_VAL_25M) + b 2f + nop +1: + li t1, SET_PLL_PD(PLL_CPU_CONFIG_VAL_40M) +2: + sw t1, AR933X_PLL_CPU_CONFIG_REG(t0) + nop +1: + lw t1, AR933X_PLL_CPU_CONFIG_REG(t0) + li t2, 0x80000000 + and t1, t1, t2 + bnez t1, 1b + nop + + /* Put frac bit19:10 configuration */ + li t1, 0x1003E8 + sw t1, AR933X_PLL_DITHER_FRAC_REG(t0) + nop + + /* Clear PLL power down bit in CPU PLL configuration */ + andi t1, t5, 0x01 # t5 BOOT_STRAP + bnez t1, 1f + nop + li t1, PLL_CPU_CONFIG_VAL_25M + b 2f + nop +1: + li t1, PLL_CPU_CONFIG_VAL_40M +2: + sw t1, AR933X_PLL_CPU_CONFIG_REG(t0) + nop + + /* Wait for PLL update -> bit 31 in CPU_PLL_CONFIG should be 0 */ +1: + lw t1, AR933X_PLL_CPU_CONFIG_REG(t0) + li t2, 0x80000000 + and t1, t1, t2 + bnez t1, 1b + nop + + /* Confirm DDR PLL lock */ + li t3, 100 + li t4, 0 + +2: + addi t4, t4, 1 + bgt t4, t3, 0b + nop + + li t3, 5 +3: + /* Clear do_meas */ + li t0, CKSEG1ADDR(AR933X_SRIF_BASE) + lw t1, AR933X_SRIF_DDR_DPLL3_REG(t0) + li t2, 0xBFFFFFFF + and t1, t1, t2 + sw t1, AR933X_SRIF_DDR_DPLL3_REG(t0) + nop + + li t2, 10 +1: + subu t2, t2, 1 + bnez t2, 1b + nop + + /* Set do_meas */ + li t2, 0x40000000 + or t1, t1, t2 + sw t1, AR933X_SRIF_DDR_DPLL3_REG(t0) + nop + + /* Check meas_done */ +1: + lw t1, AR933X_SRIF_DDR_DPLL4_REG(t0) + andi t1, t1, 0x8 + beqz t1, 1b + nop + + lw t1, AR933X_SRIF_DDR_DPLL3_REG(t0) + li t2, 0x007FFFF8 + and t1, t1, t2 + srl t1, t1, 3 + li t2, 0x4000 + bgt t1, t2, 2b + nop + addi t3, t3, -1 + bnez t3, 3b + nop + + /* clear PLL bypass (bit 2) in CPU CLOCK CONTROL register */ + li t0, CKSEG1ADDR(AR71XX_PLL_BASE) + li t1, PLL_CLK_CONTROL_VAL + sw t1, AR933X_PLL_CLK_CTRL_REG(t0) + nop + + nop + jr ra + nop + END(lowlevel_init) From 9b03f802ae63cf9c053c0125a1edd2b4c7852b9a Mon Sep 17 00:00:00 2001 From: Wills Wang Date: Wed, 16 Mar 2016 16:59:54 +0800 Subject: [PATCH 122/162] mips: ath79: add support for QCA953x SOCs This patch enable work for qca953x SOC. Signed-off-by: Wills Wang --- arch/mips/mach-ath79/Kconfig | 9 + arch/mips/mach-ath79/Makefile | 3 +- arch/mips/mach-ath79/qca953x/Makefile | 7 + arch/mips/mach-ath79/qca953x/clk.c | 111 +++++ arch/mips/mach-ath79/qca953x/ddr.c | 472 +++++++++++++++++++ arch/mips/mach-ath79/qca953x/lowlevel_init.S | 186 ++++++++ 6 files changed, 787 insertions(+), 1 deletion(-) create mode 100644 arch/mips/mach-ath79/qca953x/Makefile create mode 100644 arch/mips/mach-ath79/qca953x/clk.c create mode 100644 arch/mips/mach-ath79/qca953x/ddr.c create mode 100644 arch/mips/mach-ath79/qca953x/lowlevel_init.S diff --git a/arch/mips/mach-ath79/Kconfig b/arch/mips/mach-ath79/Kconfig index ab93d92b95..e35f1b578f 100644 --- a/arch/mips/mach-ath79/Kconfig +++ b/arch/mips/mach-ath79/Kconfig @@ -13,4 +13,13 @@ config SOC_AR933X help This supports QCA/Atheros ar933x family SOCs. +config SOC_QCA953X + bool + select SUPPORTS_BIG_ENDIAN + select SUPPORTS_CPU_MIPS32_R1 + select SUPPORTS_CPU_MIPS32_R2 + select MIPS_TUNE_24KC + help + This supports QCA/Atheros qca953x family SOCs. + endmenu diff --git a/arch/mips/mach-ath79/Makefile b/arch/mips/mach-ath79/Makefile index 9b9447e207..160dfaa146 100644 --- a/arch/mips/mach-ath79/Makefile +++ b/arch/mips/mach-ath79/Makefile @@ -6,4 +6,5 @@ obj-y += reset.o obj-y += cpu.o obj-y += dram.o -obj-$(CONFIG_SOC_AR933X) += ar933x/ \ No newline at end of file +obj-$(CONFIG_SOC_AR933X) += ar933x/ +obj-$(CONFIG_SOC_QCA953X) += qca953x/ \ No newline at end of file diff --git a/arch/mips/mach-ath79/qca953x/Makefile b/arch/mips/mach-ath79/qca953x/Makefile new file mode 100644 index 0000000000..fd74f0c2ae --- /dev/null +++ b/arch/mips/mach-ath79/qca953x/Makefile @@ -0,0 +1,7 @@ +# +# SPDX-License-Identifier: GPL-2.0+ +# + +obj-y += clk.o +obj-y += ddr.o +obj-y += lowlevel_init.o diff --git a/arch/mips/mach-ath79/qca953x/clk.c b/arch/mips/mach-ath79/qca953x/clk.c new file mode 100644 index 0000000000..ef0a28e505 --- /dev/null +++ b/arch/mips/mach-ath79/qca953x/clk.c @@ -0,0 +1,111 @@ +/* + * Copyright (C) 2015-2016 Wills Wang + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include +#include +#include + +DECLARE_GLOBAL_DATA_PTR; + +static u32 qca953x_get_xtal(void) +{ + u32 val; + + val = get_bootstrap(); + if (val & QCA953X_BOOTSTRAP_REF_CLK_40) + return 40000000; + else + return 25000000; +} + +int get_serial_clock(void) +{ + return qca953x_get_xtal(); +} + +int get_clocks(void) +{ + void __iomem *regs; + u32 val, ctrl, xtal, pll, div; + + regs = map_physmem(AR71XX_PLL_BASE, AR71XX_PLL_SIZE, + MAP_NOCACHE); + + xtal = qca953x_get_xtal(); + ctrl = readl(regs + QCA953X_PLL_CLK_CTRL_REG); + val = readl(regs + QCA953X_PLL_CPU_CONFIG_REG); + + /* VCOOUT = XTAL * DIV_INT */ + div = (val >> QCA953X_PLL_CPU_CONFIG_REFDIV_SHIFT) + & QCA953X_PLL_CPU_CONFIG_REFDIV_MASK; + pll = xtal / div; + + /* PLLOUT = VCOOUT * (1/2^OUTDIV) */ + div = (val >> QCA953X_PLL_CPU_CONFIG_NINT_SHIFT) + & QCA953X_PLL_CPU_CONFIG_NINT_MASK; + pll *= div; + div = (val >> QCA953X_PLL_CPU_CONFIG_OUTDIV_SHIFT) + & QCA953X_PLL_CPU_CONFIG_OUTDIV_MASK; + if (!div) + div = 1; + pll >>= div; + + /* CPU_CLK = PLLOUT / CPU_POST_DIV */ + div = ((ctrl >> QCA953X_PLL_CLK_CTRL_CPU_POST_DIV_SHIFT) + & QCA953X_PLL_CLK_CTRL_CPU_POST_DIV_MASK) + 1; + gd->cpu_clk = pll / div; + + + val = readl(regs + QCA953X_PLL_DDR_CONFIG_REG); + /* VCOOUT = XTAL * DIV_INT */ + div = (val >> QCA953X_PLL_DDR_CONFIG_REFDIV_SHIFT) + & QCA953X_PLL_DDR_CONFIG_REFDIV_MASK; + pll = xtal / div; + + /* PLLOUT = VCOOUT * (1/2^OUTDIV) */ + div = (val >> QCA953X_PLL_DDR_CONFIG_NINT_SHIFT) + & QCA953X_PLL_DDR_CONFIG_NINT_MASK; + pll *= div; + div = (val >> QCA953X_PLL_DDR_CONFIG_OUTDIV_SHIFT) + & QCA953X_PLL_DDR_CONFIG_OUTDIV_MASK; + if (!div) + div = 1; + pll >>= div; + + /* DDR_CLK = PLLOUT / DDR_POST_DIV */ + div = ((ctrl >> QCA953X_PLL_CLK_CTRL_DDR_POST_DIV_SHIFT) + & QCA953X_PLL_CLK_CTRL_DDR_POST_DIV_MASK) + 1; + gd->mem_clk = pll / div; + + div = ((ctrl >> QCA953X_PLL_CLK_CTRL_AHB_POST_DIV_SHIFT) + & QCA953X_PLL_CLK_CTRL_AHB_POST_DIV_MASK) + 1; + if (ctrl & QCA953X_PLL_CLK_CTRL_AHBCLK_FROM_DDRPLL) { + /* AHB_CLK = DDR_CLK / AHB_POST_DIV */ + gd->bus_clk = gd->mem_clk / (div + 1); + } else { + /* AHB_CLK = CPU_CLK / AHB_POST_DIV */ + gd->bus_clk = gd->cpu_clk / (div + 1); + } + + return 0; +} + +ulong get_bus_freq(ulong dummy) +{ + if (!gd->bus_clk) + get_clocks(); + return gd->bus_clk; +} + +ulong get_ddr_freq(ulong dummy) +{ + if (!gd->mem_clk) + get_clocks(); + return gd->mem_clk; +} diff --git a/arch/mips/mach-ath79/qca953x/ddr.c b/arch/mips/mach-ath79/qca953x/ddr.c new file mode 100644 index 0000000000..ac0130cff0 --- /dev/null +++ b/arch/mips/mach-ath79/qca953x/ddr.c @@ -0,0 +1,472 @@ +/* + * Copyright (C) 2015-2016 Wills Wang + * Based on Atheros LSDK/QSDK + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include +#include +#include + +DECLARE_GLOBAL_DATA_PTR; + +#define DDR_CTRL_UPD_EMR3S BIT(5) +#define DDR_CTRL_UPD_EMR2S BIT(4) +#define DDR_CTRL_PRECHARGE BIT(3) +#define DDR_CTRL_AUTO_REFRESH BIT(2) +#define DDR_CTRL_UPD_EMRS BIT(1) +#define DDR_CTRL_UPD_MRS BIT(0) + +#define DDR_REFRESH_EN BIT(14) +#define DDR_REFRESH_M 0x3ff +#define DDR_REFRESH(x) ((x) & DDR_REFRESH_M) +#define DDR_REFRESH_VAL (DDR_REFRESH_EN | DDR_REFRESH(312)) + +#define DDR_TRAS_S 0 +#define DDR_TRAS_M 0x1f +#define DDR_TRAS(x) (((x) & DDR_TRAS_M) << DDR_TRAS_S) +#define DDR_TRCD_M 0xf +#define DDR_TRCD_S 5 +#define DDR_TRCD(x) (((x) & DDR_TRCD_M) << DDR_TRCD_S) +#define DDR_TRP_M 0xf +#define DDR_TRP_S 9 +#define DDR_TRP(x) (((x) & DDR_TRP_M) << DDR_TRP_S) +#define DDR_TRRD_M 0xf +#define DDR_TRRD_S 13 +#define DDR_TRRD(x) (((x) & DDR_TRRD_M) << DDR_TRRD_S) +#define DDR_TRFC_M 0x7f +#define DDR_TRFC_S 17 +#define DDR_TRFC(x) (((x) & DDR_TRFC_M) << DDR_TRFC_S) +#define DDR_TMRD_M 0xf +#define DDR_TMRD_S 23 +#define DDR_TMRD(x) (((x) & DDR_TMRD_M) << DDR_TMRD_S) +#define DDR_CAS_L_M 0x17 +#define DDR_CAS_L_S 27 +#define DDR_CAS_L(x) (((x) & DDR_CAS_L_M) << DDR_CAS_L_S) +#define DDR_OPEN BIT(30) +#define DDR1_CONF_REG_VAL (DDR_TRAS(16) | DDR_TRCD(6) | \ + DDR_TRP(6) | DDR_TRRD(4) | \ + DDR_TRFC(7) | DDR_TMRD(5) | \ + DDR_CAS_L(7) | DDR_OPEN) +#define DDR2_CONF_REG_VAL (DDR_TRAS(27) | DDR_TRCD(9) | \ + DDR_TRP(9) | DDR_TRRD(7) | \ + DDR_TRFC(21) | DDR_TMRD(15) | \ + DDR_CAS_L(17) | DDR_OPEN) + +#define DDR_BURST_LEN_S 0 +#define DDR_BURST_LEN_M 0xf +#define DDR_BURST_LEN(x) ((x) << DDR_BURST_LEN_S) +#define DDR_BURST_TYPE BIT(4) +#define DDR_CNTL_OE_EN BIT(5) +#define DDR_PHASE_SEL BIT(6) +#define DDR_CKE BIT(7) +#define DDR_TWR_S 8 +#define DDR_TWR_M 0xf +#define DDR_TWR(x) (((x) & DDR_TWR_M) << DDR_TWR_S) +#define DDR_TRTW_S 12 +#define DDR_TRTW_M 0x1f +#define DDR_TRTW(x) (((x) & DDR_TRTW_M) << DDR_TRTW_S) +#define DDR_TRTP_S 17 +#define DDR_TRTP_M 0xf +#define DDR_TRTP(x) (((x) & DDR_TRTP_M) << DDR_TRTP_S) +#define DDR_TWTR_S 21 +#define DDR_TWTR_M 0x1f +#define DDR_TWTR(x) (((x) & DDR_TWTR_M) << DDR_TWTR_S) +#define DDR_G_OPEN_L_S 26 +#define DDR_G_OPEN_L_M 0xf +#define DDR_G_OPEN_L(x) ((x) << DDR_G_OPEN_L_S) +#define DDR_HALF_WIDTH_LOW BIT(31) +#define DDR1_CONF2_REG_VAL (DDR_BURST_LEN(8) | DDR_CNTL_OE_EN | \ + DDR_CKE | DDR_TWR(13) | DDR_TRTW(14) | \ + DDR_TRTP(8) | DDR_TWTR(14) | \ + DDR_G_OPEN_L(6) | DDR_HALF_WIDTH_LOW) +#define DDR2_CONF2_REG_VAL (DDR_BURST_LEN(8) | DDR_CNTL_OE_EN | \ + DDR_CKE | DDR_TWR(1) | DDR_TRTW(14) | \ + DDR_TRTP(9) | DDR_TWTR(21) | \ + DDR_G_OPEN_L(8) | DDR_HALF_WIDTH_LOW) + +#define DDR_TWR_MSB BIT(3) +#define DDR_TRAS_MSB BIT(2) +#define DDR_TRFC_MSB_M 0x3 +#define DDR_TRFC_MSB(x) (x) +#define DDR1_CONF3_REG_VAL 0 +#define DDR2_CONF3_REG_VAL (DDR_TWR_MSB | DDR_TRFC_MSB(2)) + +#define DDR_CTL_SRAM_TSEL BIT(30) +#define DDR_CTL_SRAM_GE0_SYNC BIT(20) +#define DDR_CTL_SRAM_GE1_SYNC BIT(19) +#define DDR_CTL_SRAM_USB_SYNC BIT(18) +#define DDR_CTL_SRAM_PCIE_SYNC BIT(17) +#define DDR_CTL_SRAM_WMAC_SYNC BIT(16) +#define DDR_CTL_SRAM_MISC1_SYNC BIT(15) +#define DDR_CTL_SRAM_MISC2_SYNC BIT(14) +#define DDR_CTL_PAD_DDR2_SEL BIT(6) +#define DDR_CTL_HALF_WIDTH BIT(1) +#define DDR_CTL_CONFIG_VAL (DDR_CTL_SRAM_TSEL | \ + DDR_CTL_SRAM_GE0_SYNC | \ + DDR_CTL_SRAM_GE1_SYNC | \ + DDR_CTL_SRAM_USB_SYNC | \ + DDR_CTL_SRAM_PCIE_SYNC | \ + DDR_CTL_SRAM_WMAC_SYNC | \ + DDR_CTL_HALF_WIDTH) + +#define DDR_BURST_GE0_MAX_BL_S 0 +#define DDR_BURST_GE0_MAX_BL_M 0xf +#define DDR_BURST_GE0_MAX_BL(x) \ + (((x) & DDR_BURST_GE0_MAX_BL_M) << DDR_BURST_GE0_MAX_BL_S) +#define DDR_BURST_GE1_MAX_BL_S 4 +#define DDR_BURST_GE1_MAX_BL_M 0xf +#define DDR_BURST_GE1_MAX_BL(x) \ + (((x) & DDR_BURST_GE1_MAX_BL_M) << DDR_BURST_GE1_MAX_BL_S) +#define DDR_BURST_PCIE_MAX_BL_S 8 +#define DDR_BURST_PCIE_MAX_BL_M 0xf +#define DDR_BURST_PCIE_MAX_BL(x) \ + (((x) & DDR_BURST_PCIE_MAX_BL_M) << DDR_BURST_PCIE_MAX_BL_S) +#define DDR_BURST_USB_MAX_BL_S 12 +#define DDR_BURST_USB_MAX_BL_M 0xf +#define DDR_BURST_USB_MAX_BL(x) \ + (((x) & DDR_BURST_USB_MAX_BL_M) << DDR_BURST_USB_MAX_BL_S) +#define DDR_BURST_CPU_MAX_BL_S 16 +#define DDR_BURST_CPU_MAX_BL_M 0xf +#define DDR_BURST_CPU_MAX_BL(x) \ + (((x) & DDR_BURST_CPU_MAX_BL_M) << DDR_BURST_CPU_MAX_BL_S) +#define DDR_BURST_RD_MAX_BL_S 20 +#define DDR_BURST_RD_MAX_BL_M 0xf +#define DDR_BURST_RD_MAX_BL(x) \ + (((x) & DDR_BURST_RD_MAX_BL_M) << DDR_BURST_RD_MAX_BL_S) +#define DDR_BURST_WR_MAX_BL_S 24 +#define DDR_BURST_WR_MAX_BL_M 0xf +#define DDR_BURST_WR_MAX_BL(x) \ + (((x) & DDR_BURST_WR_MAX_BL_M) << DDR_BURST_WR_MAX_BL_S) +#define DDR_BURST_RWP_MASK_EN_S 28 +#define DDR_BURST_RWP_MASK_EN_M 0x3 +#define DDR_BURST_RWP_MASK_EN(x) \ + (((x) & DDR_BURST_RWP_MASK_EN_M) << DDR_BURST_RWP_MASK_EN_S) +#define DDR_BURST_CPU_PRI_BE BIT(30) +#define DDR_BURST_CPU_PRI BIT(31) +#define DDR_BURST_VAL (DDR_BURST_CPU_PRI_BE | \ + DDR_BURST_RWP_MASK_EN(3) | \ + DDR_BURST_WR_MAX_BL(4) | \ + DDR_BURST_RD_MAX_BL(4) | \ + DDR_BURST_CPU_MAX_BL(4) | \ + DDR_BURST_USB_MAX_BL(4) | \ + DDR_BURST_PCIE_MAX_BL(4) | \ + DDR_BURST_GE1_MAX_BL(4) | \ + DDR_BURST_GE0_MAX_BL(4)) + +#define DDR_BURST_WMAC_MAX_BL_S 0 +#define DDR_BURST_WMAC_MAX_BL_M 0xf +#define DDR_BURST_WMAC_MAX_BL(x) \ + (((x) & DDR_BURST_WMAC_MAX_BL_M) << DDR_BURST_WMAC_MAX_BL_S) +#define DDR_BURST2_VAL DDR_BURST_WMAC_MAX_BL(4) + +#define DDR2_CONF_TWL_S 10 +#define DDR2_CONF_TWL_M 0xf +#define DDR2_CONF_TWL(x) \ + (((x) & DDR2_CONF_TWL_M) << DDR2_CONF_TWL_S) +#define DDR2_CONF_ODT BIT(9) +#define DDR2_CONF_TFAW_S 2 +#define DDR2_CONF_TFAW_M 0x3f +#define DDR2_CONF_TFAW(x) \ + (((x) & DDR2_CONF_TFAW_M) << DDR2_CONF_TFAW_S) +#define DDR2_CONF_EN BIT(0) +#define DDR2_CONF_VAL (DDR2_CONF_TWL(5) | \ + DDR2_CONF_TFAW(31) | \ + DDR2_CONF_ODT | \ + DDR2_CONF_EN) + +#define DDR1_EXT_MODE_VAL 0 +#define DDR2_EXT_MODE_VAL 0x402 +#define DDR2_EXT_MODE_OCD_VAL 0x782 +#define DDR1_MODE_DLL_VAL 0x133 +#define DDR2_MODE_DLL_VAL 0x143 +#define DDR1_MODE_VAL 0x33 +#define DDR2_MODE_VAL 0x43 +#define DDR1_TAP_VAL 0x20 +#define DDR2_TAP_VAL 0x10 + +#define DDR_REG_BIST_MASK_ADDR_0 0x2c +#define DDR_REG_BIST_MASK_ADDR_1 0x30 +#define DDR_REG_BIST_MASK_AHB_GE0_0 0x34 +#define DDR_REG_BIST_COMP_AHB_GE0_0 0x38 +#define DDR_REG_BIST_MASK_AHB_GE1_0 0x3c +#define DDR_REG_BIST_COMP_AHB_GE1_0 0x40 +#define DDR_REG_BIST_COMP_ADDR_0 0x64 +#define DDR_REG_BIST_COMP_ADDR_1 0x68 +#define DDR_REG_BIST_MASK_AHB_GE0_1 0x6c +#define DDR_REG_BIST_COMP_AHB_GE0_1 0x70 +#define DDR_REG_BIST_MASK_AHB_GE1_1 0x74 +#define DDR_REG_BIST_COMP_AHB_GE1_1 0x78 +#define DDR_REG_BIST 0x11c +#define DDR_REG_BIST_STATUS 0x120 + +#define DDR_BIST_COMP_CNT_S 1 +#define DDR_BIST_COMP_CNT_M 0xff +#define DDR_BIST_COMP_CNT(x) \ + (((x) & DDR_BIST_COMP_CNT_M) << DDR_BIST_COMP_CNT_S) +#define DDR_BIST_COMP_CNT_MASK \ + (DDR_BIST_COMP_CNT_M << DDR_BIST_COMP_CNT_S) +#define DDR_BIST_TEST_START BIT(0) +#define DDR_BIST_STATUS_DONE BIT(0) + +/* 4 Row Address Bits, 4 Column Address Bits, 2 BA bits */ +#define DDR_BIST_MASK_ADDR_VAL 0xfa5de83f + +#define DDR_TAP_MAGIC_VAL 0xaa55aa55 +#define DDR_TAP_MAX_VAL 0x40 + +void ddr_init(void) +{ + void __iomem *regs; + u32 val; + + regs = map_physmem(AR71XX_DDR_CTRL_BASE, AR71XX_DDR_CTRL_SIZE, + MAP_NOCACHE); + val = get_bootstrap(); + if (val & QCA953X_BOOTSTRAP_DDR1) { + writel(DDR_CTL_CONFIG_VAL, regs + QCA953X_DDR_REG_CTL_CONF); + udelay(10); + + /* For 16-bit DDR */ + writel(0xffff, regs + AR71XX_DDR_REG_RD_CYCLE); + udelay(100); + + /* Burst size */ + writel(DDR_BURST_VAL, regs + QCA953X_DDR_REG_BURST); + udelay(100); + writel(DDR_BURST2_VAL, regs + QCA953X_DDR_REG_BURST2); + udelay(100); + + /* AHB maximum timeout */ + writel(0xfffff, regs + QCA953X_DDR_REG_TIMEOUT_MAX); + udelay(100); + + /* DRAM timing */ + writel(DDR1_CONF_REG_VAL, regs + AR71XX_DDR_REG_CONFIG); + udelay(100); + writel(DDR1_CONF2_REG_VAL, regs + AR71XX_DDR_REG_CONFIG2); + udelay(100); + writel(DDR1_CONF3_REG_VAL, regs + QCA953X_DDR_REG_CONFIG3); + udelay(100); + + /* Precharge All */ + writel(DDR_CTRL_PRECHARGE, regs + AR71XX_DDR_REG_CONTROL); + udelay(100); + + /* ODT disable, Full strength, Enable DLL */ + writel(DDR1_EXT_MODE_VAL, regs + AR71XX_DDR_REG_EMR); + udelay(100); + + /* Update Extended Mode Register Set (EMRS) */ + writel(DDR_CTRL_UPD_EMRS, regs + AR71XX_DDR_REG_CONTROL); + udelay(100); + + /* Reset DLL, CAS Latency 3, Burst Length 8 */ + writel(DDR1_MODE_DLL_VAL, regs + AR71XX_DDR_REG_MODE); + udelay(100); + + /* Update Mode Register Set (MRS) */ + writel(DDR_CTRL_UPD_MRS, regs + AR71XX_DDR_REG_CONTROL); + udelay(100); + + /* Precharge All */ + writel(DDR_CTRL_PRECHARGE, regs + AR71XX_DDR_REG_CONTROL); + udelay(100); + + /* Auto Refresh */ + writel(DDR_CTRL_AUTO_REFRESH, regs + AR71XX_DDR_REG_CONTROL); + udelay(100); + writel(DDR_CTRL_AUTO_REFRESH, regs + AR71XX_DDR_REG_CONTROL); + udelay(100); + + /* Normal DLL, CAS Latency 3, Burst Length 8 */ + writel(DDR1_MODE_VAL, regs + AR71XX_DDR_REG_MODE); + udelay(100); + + /* Update Mode Register Set (MRS) */ + writel(DDR_CTRL_UPD_MRS, regs + AR71XX_DDR_REG_CONTROL); + udelay(100); + + /* Refresh time control */ + writel(DDR_REFRESH_VAL, regs + AR71XX_DDR_REG_REFRESH); + udelay(100); + + /* DQS 0 Tap Control */ + writel(DDR1_TAP_VAL, regs + AR71XX_DDR_REG_TAP_CTRL0); + + /* DQS 1 Tap Control */ + writel(DDR1_TAP_VAL, regs + AR71XX_DDR_REG_TAP_CTRL1); + } else { + writel(DDR_CTRL_UPD_EMR2S, regs + AR71XX_DDR_REG_CONTROL); + udelay(10); + writel(DDR_CTRL_UPD_EMR3S, regs + AR71XX_DDR_REG_CONTROL); + udelay(10); + writel(DDR_CTL_CONFIG_VAL | DDR_CTL_PAD_DDR2_SEL, + regs + QCA953X_DDR_REG_CTL_CONF); + udelay(10); + + /* For 16-bit DDR */ + writel(0xffff, regs + AR71XX_DDR_REG_RD_CYCLE); + udelay(100); + + /* Burst size */ + writel(DDR_BURST_VAL, regs + QCA953X_DDR_REG_BURST); + udelay(100); + writel(DDR_BURST2_VAL, regs + QCA953X_DDR_REG_BURST2); + udelay(100); + + /* AHB maximum timeout */ + writel(0xfffff, regs + QCA953X_DDR_REG_TIMEOUT_MAX); + udelay(100); + + /* DRAM timing */ + writel(DDR2_CONF_REG_VAL, regs + AR71XX_DDR_REG_CONFIG); + udelay(100); + writel(DDR2_CONF2_REG_VAL, regs + AR71XX_DDR_REG_CONFIG2); + udelay(100); + writel(DDR2_CONF3_REG_VAL, regs + QCA953X_DDR_REG_CONFIG3); + udelay(100); + + /* Enable DDR2 */ + writel(DDR2_CONF_VAL, regs + QCA953X_DDR_REG_DDR2_CONFIG); + udelay(100); + + /* Precharge All */ + writel(DDR_CTRL_PRECHARGE, regs + AR71XX_DDR_REG_CONTROL); + udelay(100); + + /* Update Extended Mode Register 2 Set (EMR2S) */ + writel(DDR_CTRL_UPD_EMR2S, regs + AR71XX_DDR_REG_CONTROL); + udelay(100); + + /* Update Extended Mode Register 3 Set (EMR3S) */ + writel(DDR_CTRL_UPD_EMR3S, regs + AR71XX_DDR_REG_CONTROL); + udelay(100); + + /* 150 ohm, Reduced strength, Enable DLL */ + writel(DDR2_EXT_MODE_VAL, regs + AR71XX_DDR_REG_EMR); + udelay(100); + + /* Update Extended Mode Register Set (EMRS) */ + writel(DDR_CTRL_UPD_EMRS, regs + AR71XX_DDR_REG_CONTROL); + udelay(100); + + /* Reset DLL, CAS Latency 4, Burst Length 8 */ + writel(DDR2_MODE_DLL_VAL, regs + AR71XX_DDR_REG_MODE); + udelay(100); + + /* Update Mode Register Set (MRS) */ + writel(DDR_CTRL_UPD_MRS, regs + AR71XX_DDR_REG_CONTROL); + udelay(100); + + /* Precharge All */ + writel(DDR_CTRL_PRECHARGE, regs + AR71XX_DDR_REG_CONTROL); + udelay(100); + + /* Auto Refresh */ + writel(DDR_CTRL_AUTO_REFRESH, regs + AR71XX_DDR_REG_CONTROL); + udelay(100); + writel(DDR_CTRL_AUTO_REFRESH, regs + AR71XX_DDR_REG_CONTROL); + udelay(100); + + /* Normal DLL, CAS Latency 4, Burst Length 8 */ + writel(DDR2_MODE_VAL, regs + AR71XX_DDR_REG_MODE); + udelay(100); + + /* Mode Register Set (MRS) */ + writel(DDR_CTRL_UPD_MRS, regs + AR71XX_DDR_REG_CONTROL); + udelay(100); + + /* Enable OCD, Enable DLL, Reduced Drive Strength */ + writel(DDR2_EXT_MODE_OCD_VAL, regs + AR71XX_DDR_REG_EMR); + udelay(100); + + /* Update Extended Mode Register Set (EMRS) */ + writel(DDR_CTRL_UPD_EMRS, regs + AR71XX_DDR_REG_CONTROL); + udelay(100); + + /* OCD diable, Enable DLL, Reduced Drive Strength */ + writel(DDR2_EXT_MODE_VAL, regs + AR71XX_DDR_REG_EMR); + udelay(100); + + /* Update Extended Mode Register Set (EMRS) */ + writel(DDR_CTRL_UPD_EMRS, regs + AR71XX_DDR_REG_CONTROL); + udelay(100); + + /* Refresh time control */ + writel(DDR_REFRESH_VAL, regs + AR71XX_DDR_REG_REFRESH); + udelay(100); + + /* DQS 0 Tap Control */ + writel(DDR2_TAP_VAL, regs + AR71XX_DDR_REG_TAP_CTRL0); + + /* DQS 1 Tap Control */ + writel(DDR2_TAP_VAL, regs + AR71XX_DDR_REG_TAP_CTRL1); + } +} + +void ddr_tap_tuning(void) +{ + void __iomem *regs; + u32 val, pass, tap, cnt, tap_val, last, first; + + regs = map_physmem(AR71XX_DDR_CTRL_BASE, AR71XX_DDR_CTRL_SIZE, + MAP_NOCACHE); + + tap_val = readl(regs + AR71XX_DDR_REG_TAP_CTRL0); + first = DDR_TAP_MAGIC_VAL; + last = 0; + cnt = 0; + tap = 0; + + do { + writel(tap, regs + AR71XX_DDR_REG_TAP_CTRL0); + writel(tap, regs + AR71XX_DDR_REG_TAP_CTRL1); + + writel(DDR_BIST_COMP_CNT(8), regs + DDR_REG_BIST_COMP_ADDR_1); + writel(DDR_BIST_MASK_ADDR_VAL, regs + DDR_REG_BIST_MASK_ADDR_0); + writel(0xffff, regs + DDR_REG_BIST_COMP_AHB_GE0_1); + writel(0xffff, regs + DDR_REG_BIST_COMP_AHB_GE1_0); + writel(0xffff, regs + DDR_REG_BIST_COMP_AHB_GE1_1); + writel(0xffff, regs + DDR_REG_BIST_MASK_AHB_GE0_0); + writel(0xffff, regs + DDR_REG_BIST_MASK_AHB_GE0_1); + writel(0xffff, regs + DDR_REG_BIST_MASK_AHB_GE1_0); + writel(0xffff, regs + DDR_REG_BIST_MASK_AHB_GE1_1); + writel(0xffff, regs + DDR_REG_BIST_COMP_AHB_GE0_0); + + /* Start BIST test */ + writel(DDR_BIST_TEST_START, regs + DDR_REG_BIST); + + do { + val = readl(regs + DDR_REG_BIST_STATUS); + } while (!(val & DDR_BIST_STATUS_DONE)); + + /* Stop BIST test */ + writel(0, regs + DDR_REG_BIST); + + pass = val & DDR_BIST_COMP_CNT_MASK; + pass ^= DDR_BIST_COMP_CNT(8); + if (!pass) { + if (first != DDR_TAP_MAGIC_VAL) { + last = tap; + } else { + first = tap; + last = tap; + } + cnt++; + } + tap++; + } while (tap < DDR_TAP_MAX_VAL); + + if (cnt) { + tap_val = (first + last) / 2; + tap_val %= DDR_TAP_MAX_VAL; + } + + writel(tap_val, regs + AR71XX_DDR_REG_TAP_CTRL0); + writel(tap_val, regs + AR71XX_DDR_REG_TAP_CTRL1); +} diff --git a/arch/mips/mach-ath79/qca953x/lowlevel_init.S b/arch/mips/mach-ath79/qca953x/lowlevel_init.S new file mode 100644 index 0000000000..d7038faa6a --- /dev/null +++ b/arch/mips/mach-ath79/qca953x/lowlevel_init.S @@ -0,0 +1,186 @@ +/* + * Copyright (C) 2015-2016 Wills Wang + * Based on Atheros LSDK/QSDK + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include +#include +#include + +#define MK_PLL_CONF(divint, refdiv, range, outdiv) \ + (((0x3F & divint) << 10) | \ + ((0x1F & refdiv) << 16) | \ + ((0x1 & range) << 21) | \ + ((0x7 & outdiv) << 23) ) + +#define MK_CLK_CNTL(cpudiv, ddrdiv, ahbdiv) \ + (((0x3 & (cpudiv - 1)) << 5) | \ + ((0x3 & (ddrdiv - 1)) << 10) | \ + ((0x3 & (ahbdiv - 1)) << 15) ) + +#define SET_FIELD(name, v) (((v) & QCA953X_##name##_MASK) << \ + QCA953X_##name##_SHIFT) + +#define DPLL2_KI(v) SET_FIELD(SRIF_DPLL2_KI, v) +#define DPLL2_KD(v) SET_FIELD(SRIF_DPLL2_KD, v) +#define DPLL2_PWD QCA953X_SRIF_DPLL2_PWD +#define MK_DPLL2(ki, kd) (DPLL2_KI(ki) | DPLL2_KD(kd) | DPLL2_PWD) + +#define PLL_CPU_NFRAC(v) SET_FIELD(PLL_CPU_CONFIG_NFRAC, v) +#define PLL_CPU_NINT(v) SET_FIELD(PLL_CPU_CONFIG_NINT, v) +#define PLL_CPU_REFDIV(v) SET_FIELD(PLL_CPU_CONFIG_REFDIV, v) +#define PLL_CPU_OUTDIV(v) SET_FIELD(PLL_CPU_CONFIG_OUTDIV, v) +#define MK_PLL_CPU_CONF(frac, nint, ref, outdiv) \ + (PLL_CPU_NFRAC(frac) | \ + PLL_CPU_NINT(nint) | \ + PLL_CPU_REFDIV(ref) | \ + PLL_CPU_OUTDIV(outdiv)) + +#define PLL_DDR_NFRAC(v) SET_FIELD(PLL_DDR_CONFIG_NFRAC, v) +#define PLL_DDR_NINT(v) SET_FIELD(PLL_DDR_CONFIG_NINT, v) +#define PLL_DDR_REFDIV(v) SET_FIELD(PLL_DDR_CONFIG_REFDIV, v) +#define PLL_DDR_OUTDIV(v) SET_FIELD(PLL_DDR_CONFIG_OUTDIV, v) +#define MK_PLL_DDR_CONF(frac, nint, ref, outdiv) \ + (PLL_DDR_NFRAC(frac) | \ + PLL_DDR_REFDIV(ref) | \ + PLL_DDR_NINT(nint) | \ + PLL_DDR_OUTDIV(outdiv) | \ + QCA953X_PLL_CONFIG_PWD) + +#define PLL_CPU_CONF_VAL MK_PLL_CPU_CONF(0, 26, 1, 0) +#define PLL_DDR_CONF_VAL MK_PLL_DDR_CONF(0, 15, 1, 0) + +#define PLL_CLK_CTRL_PLL_BYPASS (QCA953X_PLL_CLK_CTRL_CPU_PLL_BYPASS | \ + QCA953X_PLL_CLK_CTRL_DDR_PLL_BYPASS | \ + QCA953X_PLL_CLK_CTRL_AHB_PLL_BYPASS) + +#define PLL_CLK_CTRL_CPU_DIV(v) SET_FIELD(PLL_CLK_CTRL_CPU_POST_DIV, v) +#define PLL_CLK_CTRL_DDR_DIV(v) SET_FIELD(PLL_CLK_CTRL_DDR_POST_DIV, v) +#define PLL_CLK_CTRL_AHB_DIV(v) SET_FIELD(PLL_CLK_CTRL_AHB_POST_DIV, v) +#define MK_PLL_CLK_CTRL(cpu, ddr, ahb) \ + (PLL_CLK_CTRL_CPU_DIV(cpu) | \ + PLL_CLK_CTRL_DDR_DIV(ddr) | \ + PLL_CLK_CTRL_AHB_DIV(ahb)) +#define PLL_CLK_CTRL_VAL (MK_PLL_CLK_CTRL(0, 0, 2) | \ + PLL_CLK_CTRL_PLL_BYPASS | \ + QCA953X_PLL_CLK_CTRL_CPUCLK_FROM_CPUPLL | \ + QCA953X_PLL_CLK_CTRL_DDRCLK_FROM_DDRPLL) + +#define PLL_DDR_DIT_FRAC_MAX(v) SET_FIELD(PLL_DDR_DIT_FRAC_MAX, v) +#define PLL_DDR_DIT_FRAC_MIN(v) SET_FIELD(PLL_DDR_DIT_FRAC_MIN, v) +#define PLL_DDR_DIT_FRAC_STEP(v) SET_FIELD(PLL_DDR_DIT_FRAC_STEP, v) +#define PLL_DDR_DIT_UPD_CNT(v) SET_FIELD(PLL_DDR_DIT_UPD_CNT, v) +#define PLL_CPU_DIT_FRAC_MAX(v) SET_FIELD(PLL_CPU_DIT_FRAC_MAX, v) +#define PLL_CPU_DIT_FRAC_MIN(v) SET_FIELD(PLL_CPU_DIT_FRAC_MIN, v) +#define PLL_CPU_DIT_FRAC_STEP(v) SET_FIELD(PLL_CPU_DIT_FRAC_STEP, v) +#define PLL_CPU_DIT_UPD_CNT(v) SET_FIELD(PLL_CPU_DIT_UPD_CNT, v) +#define MK_PLL_DDR_DIT_FRAC(max, min, step, cnt) \ + (QCA953X_PLL_DIT_FRAC_EN | \ + PLL_DDR_DIT_FRAC_MAX(max) | \ + PLL_DDR_DIT_FRAC_MIN(min) | \ + PLL_DDR_DIT_FRAC_STEP(step) | \ + PLL_DDR_DIT_UPD_CNT(cnt)) +#define MK_PLL_CPU_DIT_FRAC(max, min, step, cnt) \ + (QCA953X_PLL_DIT_FRAC_EN | \ + PLL_CPU_DIT_FRAC_MAX(max) | \ + PLL_CPU_DIT_FRAC_MIN(min) | \ + PLL_CPU_DIT_FRAC_STEP(step) | \ + PLL_CPU_DIT_UPD_CNT(cnt)) +#define PLL_CPU_DIT_FRAC_VAL MK_PLL_CPU_DIT_FRAC(63, 0, 1, 15) +#define PLL_DDR_DIT_FRAC_VAL MK_PLL_DDR_DIT_FRAC(763, 635, 1, 15) + + .text + .set noreorder + +LEAF(lowlevel_init) + /* RTC Reset */ + li t0, CKSEG1ADDR(AR71XX_RESET_BASE) + lw t1, QCA953X_RESET_REG_RESET_MODULE(t0) + li t2, 0x08000000 + or t1, t1, t2 + sw t1, QCA953X_RESET_REG_RESET_MODULE(t0) + nop + lw t1, QCA953X_RESET_REG_RESET_MODULE(t0) + li t2, 0xf7ffffff + and t1, t1, t2 + sw t1, QCA953X_RESET_REG_RESET_MODULE(t0) + nop + + /* RTC Force Wake */ + li t0, CKSEG1ADDR(QCA953X_RTC_BASE) + li t1, 0x01 + sw t1, QCA953X_RTC_REG_SYNC_RESET(t0) + nop + nop + + /* Wait for RTC in on state */ +1: + lw t1, QCA953X_RTC_REG_SYNC_STATUS(t0) + andi t1, t1, 0x02 + beqz t1, 1b + nop + + li t0, CKSEG1ADDR(QCA953X_SRIF_BASE) + li t1, MK_DPLL2(2, 16) + sw t1, QCA953X_SRIF_BB_DPLL2_REG(t0) + sw t1, QCA953X_SRIF_PCIE_DPLL2_REG(t0) + sw t1, QCA953X_SRIF_DDR_DPLL2_REG(t0) + sw t1, QCA953X_SRIF_CPU_DPLL2_REG(t0) + + li t0, CKSEG1ADDR(AR71XX_PLL_BASE) + lw t1, QCA953X_PLL_CLK_CTRL_REG(t0) + ori t1, PLL_CLK_CTRL_PLL_BYPASS + sw t1, QCA953X_PLL_CLK_CTRL_REG(t0) + nop + + li t1, PLL_CPU_CONF_VAL + sw t1, QCA953X_PLL_CPU_CONFIG_REG(t0) + nop + + li t1, PLL_DDR_CONF_VAL + sw t1, QCA953X_PLL_DDR_CONFIG_REG(t0) + nop + + li t1, PLL_CLK_CTRL_VAL + sw t1, QCA953X_PLL_CLK_CTRL_REG(t0) + nop + + lw t1, QCA953X_PLL_CPU_CONFIG_REG(t0) + li t2, ~QCA953X_PLL_CONFIG_PWD + and t1, t1, t2 + sw t1, QCA953X_PLL_CPU_CONFIG_REG(t0) + nop + + lw t1, QCA953X_PLL_DDR_CONFIG_REG(t0) + li t2, ~QCA953X_PLL_CONFIG_PWD + and t1, t1, t2 + sw t1, QCA953X_PLL_DDR_CONFIG_REG(t0) + nop + + lw t1, QCA953X_PLL_CLK_CTRL_REG(t0) + li t2, ~PLL_CLK_CTRL_PLL_BYPASS + and t1, t1, t2 + sw t1, QCA953X_PLL_CLK_CTRL_REG(t0) + nop + + li t1, PLL_DDR_DIT_FRAC_VAL + sw t1, QCA953X_PLL_DDR_DIT_FRAC_REG(t0) + nop + + li t1, PLL_CPU_DIT_FRAC_VAL + sw t1, QCA953X_PLL_CPU_DIT_FRAC_REG(t0) + nop + + li t0, CKSEG1ADDR(AR71XX_RESET_BASE) + lui t1, 0x03fc + sw t1, 0xb4(t0) + + nop + jr ra + nop + END(lowlevel_init) From a79d0643f4cac19711cb8d1c2088fc907d47500f Mon Sep 17 00:00:00 2001 From: Wills Wang Date: Wed, 16 Mar 2016 16:59:55 +0800 Subject: [PATCH 123/162] drivers: pinctrl: Add simple pinctrl driver for Qualcomm/Atheros ar933x. This is a simple pinctrl driver, it just support uart and spi pin-mux now. Signed-off-by: Wills Wang Reviewed-by: Simon Glass [fixed typo in commit subject line] Signed-off-by: Daniel Schwierzeck --- drivers/pinctrl/Kconfig | 9 ++ drivers/pinctrl/Makefile | 1 + drivers/pinctrl/ath79/Makefile | 5 + drivers/pinctrl/ath79/pinctrl_ar933x.c | 136 +++++++++++++++++++++++++ 4 files changed, 151 insertions(+) create mode 100644 drivers/pinctrl/ath79/Makefile create mode 100644 drivers/pinctrl/ath79/pinctrl_ar933x.c diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig index 2a69babec4..854d5a500a 100644 --- a/drivers/pinctrl/Kconfig +++ b/drivers/pinctrl/Kconfig @@ -105,6 +105,15 @@ config SPL_PINCONF if PINCTRL || SPL_PINCTRL +config AR933X_PINCTRL + bool "QCA/Athores ar933x pin control driver" + depends on DM && SOC_AR933X + help + Support pin multiplexing control on QCA/Athores ar933x SoCs. + The driver is controlled by a device tree node which contains + both the GPIO definitions and pin control functions for each + available multiplex function. + config ROCKCHIP_PINCTRL bool "Rockchip pin control driver" depends on DM diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile index 37dc904640..b99ed2f191 100644 --- a/drivers/pinctrl/Makefile +++ b/drivers/pinctrl/Makefile @@ -6,6 +6,7 @@ obj-y += pinctrl-uclass.o obj-$(CONFIG_$(SPL_)PINCTRL_GENERIC) += pinctrl-generic.o obj-y += nxp/ +obj-$(CONFIG_ARCH_ATH79) += ath79/ obj-$(CONFIG_ARCH_ROCKCHIP) += rockchip/ obj-$(CONFIG_PINCTRL_SANDBOX) += pinctrl-sandbox.o diff --git a/drivers/pinctrl/ath79/Makefile b/drivers/pinctrl/ath79/Makefile new file mode 100644 index 0000000000..3fdcf6c4b8 --- /dev/null +++ b/drivers/pinctrl/ath79/Makefile @@ -0,0 +1,5 @@ +# +# SPDX-License-Identifier: GPL-2.0+ +# + +obj-$(CONFIG_AR933X_PINCTRL) += pinctrl_ar933x.o diff --git a/drivers/pinctrl/ath79/pinctrl_ar933x.c b/drivers/pinctrl/ath79/pinctrl_ar933x.c new file mode 100644 index 0000000000..e3f64b6355 --- /dev/null +++ b/drivers/pinctrl/ath79/pinctrl_ar933x.c @@ -0,0 +1,136 @@ +/* + * Copyright (C) 2015-2016 Wills Wang + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include +#include +#include + +DECLARE_GLOBAL_DATA_PTR; + +enum periph_id { + PERIPH_ID_UART0, + PERIPH_ID_SPI0, + PERIPH_ID_NONE = -1, +}; + +struct ar933x_pinctrl_priv { + void __iomem *regs; +}; + +static void pinctrl_ar933x_spi_config(struct ar933x_pinctrl_priv *priv, int cs) +{ + switch (cs) { + case 0: + clrsetbits_be32(priv->regs + AR71XX_GPIO_REG_OE, + AR933X_GPIO(4), AR933X_GPIO(3) | + AR933X_GPIO(5) | AR933X_GPIO(2)); + setbits_be32(priv->regs + AR71XX_GPIO_REG_FUNC, + AR933X_GPIO_FUNC_SPI_EN | + AR933X_GPIO_FUNC_RES_TRUE); + break; + } +} + +static void pinctrl_ar933x_uart_config(struct ar933x_pinctrl_priv *priv, int uart_id) +{ + switch (uart_id) { + case PERIPH_ID_UART0: + clrsetbits_be32(priv->regs + AR71XX_GPIO_REG_OE, + AR933X_GPIO(9), AR933X_GPIO(10)); + setbits_be32(priv->regs + AR71XX_GPIO_REG_FUNC, + AR933X_GPIO_FUNC_UART_EN | + AR933X_GPIO_FUNC_RES_TRUE); + break; + } +} + +static int ar933x_pinctrl_request(struct udevice *dev, int func, int flags) +{ + struct ar933x_pinctrl_priv *priv = dev_get_priv(dev); + + debug("%s: func=%x, flags=%x\n", __func__, func, flags); + switch (func) { + case PERIPH_ID_SPI0: + pinctrl_ar933x_spi_config(priv, flags); + break; + case PERIPH_ID_UART0: + pinctrl_ar933x_uart_config(priv, func); + break; + default: + return -EINVAL; + } + + return 0; +} + +static int ar933x_pinctrl_get_periph_id(struct udevice *dev, + struct udevice *periph) +{ + u32 cell[2]; + int ret; + + ret = fdtdec_get_int_array(gd->fdt_blob, periph->of_offset, + "interrupts", cell, ARRAY_SIZE(cell)); + if (ret < 0) + return -EINVAL; + + switch (cell[0]) { + case 128: + return PERIPH_ID_UART0; + case 129: + return PERIPH_ID_SPI0; + } + return -ENOENT; +} + +static int ar933x_pinctrl_set_state_simple(struct udevice *dev, + struct udevice *periph) +{ + int func; + + func = ar933x_pinctrl_get_periph_id(dev, periph); + if (func < 0) + return func; + return ar933x_pinctrl_request(dev, func, 0); +} + +static struct pinctrl_ops ar933x_pinctrl_ops = { + .set_state_simple = ar933x_pinctrl_set_state_simple, + .request = ar933x_pinctrl_request, + .get_periph_id = ar933x_pinctrl_get_periph_id, +}; + +static int ar933x_pinctrl_probe(struct udevice *dev) +{ + struct ar933x_pinctrl_priv *priv = dev_get_priv(dev); + fdt_addr_t addr; + + addr = dev_get_addr(dev); + if (addr == FDT_ADDR_T_NONE) + return -EINVAL; + + priv->regs = map_physmem(addr, + AR71XX_GPIO_SIZE, + MAP_NOCACHE); + return 0; +} + +static const struct udevice_id ar933x_pinctrl_ids[] = { + { .compatible = "qca,ar933x-pinctrl" }, + { } +}; + +U_BOOT_DRIVER(pinctrl_ar933x) = { + .name = "pinctrl_ar933x", + .id = UCLASS_PINCTRL, + .of_match = ar933x_pinctrl_ids, + .priv_auto_alloc_size = sizeof(struct ar933x_pinctrl_priv), + .ops = &ar933x_pinctrl_ops, + .probe = ar933x_pinctrl_probe, +}; From c102453aebe92530962de41539ce4f198d27b9c7 Mon Sep 17 00:00:00 2001 From: Wills Wang Date: Wed, 16 Mar 2016 16:59:56 +0800 Subject: [PATCH 124/162] drivers: pinctrl: Add simple pinctrl driver for Qualcomm/Atheros qca953x. This is a simple pinctrl driver, it just support uart and spi pin-mux now. Signed-off-by: Wills Wang Reviewed-by: Simon Glass [fixed typo in commit subject line] Signed-off-by: Daniel Schwierzeck --- drivers/pinctrl/Kconfig | 9 ++ drivers/pinctrl/ath79/Makefile | 1 + drivers/pinctrl/ath79/pinctrl_qca953x.c | 156 ++++++++++++++++++++++++ 3 files changed, 166 insertions(+) create mode 100644 drivers/pinctrl/ath79/pinctrl_qca953x.c diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig index 854d5a500a..567b7662d0 100644 --- a/drivers/pinctrl/Kconfig +++ b/drivers/pinctrl/Kconfig @@ -114,6 +114,15 @@ config AR933X_PINCTRL both the GPIO definitions and pin control functions for each available multiplex function. +config QCA953X_PINCTRL + bool "QCA/Athores qca953x pin control driver" + depends on DM && SOC_QCA953X + help + Support pin multiplexing control on QCA/Athores qca953x SoCs. + The driver is controlled by a device tree node which contains + both the GPIO definitions and pin control functions for each + available multiplex function. + config ROCKCHIP_PINCTRL bool "Rockchip pin control driver" depends on DM diff --git a/drivers/pinctrl/ath79/Makefile b/drivers/pinctrl/ath79/Makefile index 3fdcf6c4b8..dcea10ace6 100644 --- a/drivers/pinctrl/ath79/Makefile +++ b/drivers/pinctrl/ath79/Makefile @@ -3,3 +3,4 @@ # obj-$(CONFIG_AR933X_PINCTRL) += pinctrl_ar933x.o +obj-$(CONFIG_QCA953x_PINCTRL) += pinctrl_qca953x.o diff --git a/drivers/pinctrl/ath79/pinctrl_qca953x.c b/drivers/pinctrl/ath79/pinctrl_qca953x.c new file mode 100644 index 0000000000..d02597e968 --- /dev/null +++ b/drivers/pinctrl/ath79/pinctrl_qca953x.c @@ -0,0 +1,156 @@ +/* + * Copyright (C) 2015-2016 Wills Wang + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include +#include +#include + +DECLARE_GLOBAL_DATA_PTR; + +enum periph_id { + PERIPH_ID_UART0, + PERIPH_ID_SPI0, + PERIPH_ID_NONE = -1, +}; + +struct qca953x_pinctrl_priv { + void __iomem *regs; +}; + +static void pinctrl_qca953x_spi_config(struct qca953x_pinctrl_priv *priv, int cs) +{ + switch (cs) { + case 0: + clrsetbits_be32(priv->regs + AR71XX_GPIO_REG_OE, + QCA953X_GPIO(5) | QCA953X_GPIO(6) | + QCA953X_GPIO(7), QCA953X_GPIO(8)); + + clrsetbits_be32(priv->regs + QCA953X_GPIO_REG_OUT_FUNC1, + QCA953X_GPIO_MUX_MASK(8) | + QCA953X_GPIO_MUX_MASK(16) | + QCA953X_GPIO_MUX_MASK(24), + (QCA953X_GPIO_OUT_MUX_SPI_CS0 << 8) | + (QCA953X_GPIO_OUT_MUX_SPI_CLK << 16) | + (QCA953X_GPIO_OUT_MUX_SPI_MOSI << 24)); + + clrsetbits_be32(priv->regs + QCA953X_GPIO_REG_IN_ENABLE0, + QCA953X_GPIO_MUX_MASK(0), + QCA953X_GPIO_IN_MUX_SPI_DATA_IN); + + setbits_be32(priv->regs + AR71XX_GPIO_REG_OUT, + QCA953X_GPIO(8)); + break; + } +} + +static void pinctrl_qca953x_uart_config(struct qca953x_pinctrl_priv *priv, int uart_id) +{ + switch (uart_id) { + case PERIPH_ID_UART0: + clrsetbits_be32(priv->regs + AR71XX_GPIO_REG_OE, + QCA953X_GPIO(9), QCA953X_GPIO(10)); + + clrsetbits_be32(priv->regs + QCA953X_GPIO_REG_OUT_FUNC2, + QCA953X_GPIO_MUX_MASK(16), + QCA953X_GPIO_OUT_MUX_UART0_SOUT << 16); + + clrsetbits_be32(priv->regs + QCA953X_GPIO_REG_IN_ENABLE0, + QCA953X_GPIO_MUX_MASK(8), + QCA953X_GPIO_IN_MUX_UART0_SIN << 8); + + setbits_be32(priv->regs + AR71XX_GPIO_REG_OUT, + QCA953X_GPIO(10)); + break; + } +} + +static int qca953x_pinctrl_request(struct udevice *dev, int func, int flags) +{ + struct qca953x_pinctrl_priv *priv = dev_get_priv(dev); + + debug("%s: func=%x, flags=%x\n", __func__, func, flags); + switch (func) { + case PERIPH_ID_SPI0: + pinctrl_qca953x_spi_config(priv, flags); + break; + case PERIPH_ID_UART0: + pinctrl_qca953x_uart_config(priv, func); + break; + default: + return -EINVAL; + } + + return 0; +} + +static int qca953x_pinctrl_get_periph_id(struct udevice *dev, + struct udevice *periph) +{ + u32 cell[2]; + int ret; + + ret = fdtdec_get_int_array(gd->fdt_blob, periph->of_offset, + "interrupts", cell, ARRAY_SIZE(cell)); + if (ret < 0) + return -EINVAL; + + switch (cell[0]) { + case 128: + return PERIPH_ID_UART0; + case 129: + return PERIPH_ID_SPI0; + } + return -ENOENT; +} + +static int qca953x_pinctrl_set_state_simple(struct udevice *dev, + struct udevice *periph) +{ + int func; + + func = qca953x_pinctrl_get_periph_id(dev, periph); + if (func < 0) + return func; + return qca953x_pinctrl_request(dev, func, 0); +} + +static struct pinctrl_ops qca953x_pinctrl_ops = { + .set_state_simple = qca953x_pinctrl_set_state_simple, + .request = qca953x_pinctrl_request, + .get_periph_id = qca953x_pinctrl_get_periph_id, +}; + +static int qca953x_pinctrl_probe(struct udevice *dev) +{ + struct qca953x_pinctrl_priv *priv = dev_get_priv(dev); + fdt_addr_t addr; + + addr = dev_get_addr(dev); + if (addr == FDT_ADDR_T_NONE) + return -EINVAL; + + priv->regs = map_physmem(addr, + AR71XX_GPIO_SIZE, + MAP_NOCACHE); + return 0; +} + +static const struct udevice_id qca953x_pinctrl_ids[] = { + { .compatible = "qca,qca953x-pinctrl" }, + { } +}; + +U_BOOT_DRIVER(pinctrl_qca953x) = { + .name = "pinctrl_qca953x", + .id = UCLASS_PINCTRL, + .of_match = qca953x_pinctrl_ids, + .priv_auto_alloc_size = sizeof(struct qca953x_pinctrl_priv), + .ops = &qca953x_pinctrl_ops, + .probe = qca953x_pinctrl_probe, +}; From 60b49761e9d2f0d16ac5cef934504bc895ac3913 Mon Sep 17 00:00:00 2001 From: Wills Wang Date: Wed, 16 Mar 2016 16:59:57 +0800 Subject: [PATCH 125/162] drivers: serial: add serial driver for ar933x SOC This patch add support for ar933x serial. Signed-off-by: Wills Wang Reviewed-by: Thomas Chou Reviewed-by: Daniel Schwierzeck Reviewed-by: Simon Glass --- .../serial/qca,ar9330-uart.txt | 24 ++ drivers/serial/Kconfig | 18 ++ drivers/serial/Makefile | 1 + drivers/serial/serial_ar933x.c | 255 ++++++++++++++++++ 4 files changed, 298 insertions(+) create mode 100644 doc/device-tree-bindings/serial/qca,ar9330-uart.txt create mode 100644 drivers/serial/serial_ar933x.c diff --git a/doc/device-tree-bindings/serial/qca,ar9330-uart.txt b/doc/device-tree-bindings/serial/qca,ar9330-uart.txt new file mode 100644 index 0000000000..ec576a1ce9 --- /dev/null +++ b/doc/device-tree-bindings/serial/qca,ar9330-uart.txt @@ -0,0 +1,24 @@ +* Qualcomm Atheros AR9330 High-Speed UART + +Required properties: + +- compatible: Must be "qca,ar9330-uart" + +- reg: Specifies the physical base address of the controller and + the length of the memory mapped region. + +Additional requirements: + + Each UART port must have an alias correctly numbered in "aliases" + node. + +Example: + + aliases { + serial0 = &uart0; + }; + + uart0: uart@18020000 { + compatible = "qca,ar9330-uart"; + reg = <0x18020000 0x14>; + }; diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index a9a5d475dd..2497ae90a0 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig @@ -89,6 +89,15 @@ config DEBUG_UART_ALTERA_UART You will need to provide parameters to make this work. The driver will be available until the real driver model serial is running. +config DEBUG_UART_AR933X + bool "QCA/Atheros ar933x" + depends on AR933X_UART + help + Select this to enable a debug UART using the ar933x uart driver. + You will need to provide parameters to make this work. The + driver will be available until the real driver model serial is + running. + config DEBUG_UART_NS16550 bool "ns16550" help @@ -263,6 +272,15 @@ config ALTERA_UART Select this to enable an UART for Altera devices. Please find details on the "Embedded Peripherals IP User Guide" of Altera. +config AR933X_UART + bool "QCA/Atheros ar933x UART support" + depends on DM_SERIAL && SOC_AR933X + help + Select this to enable UART support for QCA/Atheros ar933x + devices. This driver uses driver model and requires a device + tree binding to operate, please refer to the document at + doc/device-tree-bindings/serial/qca,ar9330-uart.txt. + config FSL_LPUART bool "Freescale LPUART support" help diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile index b0ac9d8a56..9def128e89 100644 --- a/drivers/serial/Makefile +++ b/drivers/serial/Makefile @@ -17,6 +17,7 @@ endif obj-$(CONFIG_ALTERA_UART) += altera_uart.o obj-$(CONFIG_ALTERA_JTAG_UART) += altera_jtag_uart.o +obj-$(CONFIG_AR933X_UART) += serial_ar933x.o obj-$(CONFIG_ARM_DCC) += arm_dcc.o obj-$(CONFIG_ATMEL_USART) += atmel_usart.o obj-$(CONFIG_EFI_APP) += serial_efi.o diff --git a/drivers/serial/serial_ar933x.c b/drivers/serial/serial_ar933x.c new file mode 100644 index 0000000000..d43f9c97d7 --- /dev/null +++ b/drivers/serial/serial_ar933x.c @@ -0,0 +1,255 @@ +/* + * Copyright (C) 2015-2016 Wills Wang + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define AR933X_UART_DATA_REG 0x00 +#define AR933X_UART_CS_REG 0x04 +#define AR933X_UART_CLK_REG 0x08 + +#define AR933X_UART_DATA_TX_RX_MASK 0xff +#define AR933X_UART_DATA_RX_CSR BIT(8) +#define AR933X_UART_DATA_TX_CSR BIT(9) +#define AR933X_UART_CS_IF_MODE_S 2 +#define AR933X_UART_CS_IF_MODE_M 0x3 +#define AR933X_UART_CS_IF_MODE_DTE 1 +#define AR933X_UART_CS_IF_MODE_DCE 2 +#define AR933X_UART_CS_TX_RDY_ORIDE BIT(7) +#define AR933X_UART_CS_RX_RDY_ORIDE BIT(8) +#define AR933X_UART_CLK_STEP_M 0xffff +#define AR933X_UART_CLK_SCALE_M 0xfff +#define AR933X_UART_CLK_SCALE_S 16 +#define AR933X_UART_CLK_STEP_S 0 + +struct ar933x_serial_priv { + void __iomem *regs; +}; + +/* + * baudrate = (clk / (scale + 1)) * (step * (1 / 2^17)) + */ +static u32 ar933x_serial_get_baud(u32 clk, u32 scale, u32 step) +{ + u64 t; + u32 div; + + div = (2 << 16) * (scale + 1); + t = clk; + t *= step; + t += (div / 2); + do_div(t, div); + + return t; +} + +static void ar933x_serial_get_scale_step(u32 clk, u32 baud, + u32 *scale, u32 *step) +{ + u32 tscale, baudrate; + long min_diff; + + *scale = 0; + *step = 0; + + min_diff = baud; + for (tscale = 0; tscale < AR933X_UART_CLK_SCALE_M; tscale++) { + u64 tstep; + int diff; + + tstep = baud * (tscale + 1); + tstep *= (2 << 16); + do_div(tstep, clk); + + if (tstep > AR933X_UART_CLK_STEP_M) + break; + + baudrate = ar933x_serial_get_baud(clk, tscale, tstep); + diff = abs(baudrate - baud); + if (diff < min_diff) { + min_diff = diff; + *scale = tscale; + *step = tstep; + } + } +} + +static int ar933x_serial_setbrg(struct udevice *dev, int baudrate) +{ + struct ar933x_serial_priv *priv = dev_get_priv(dev); + u32 val, scale, step; + + val = get_serial_clock(); + ar933x_serial_get_scale_step(val, baudrate, &scale, &step); + + val = (scale & AR933X_UART_CLK_SCALE_M) + << AR933X_UART_CLK_SCALE_S; + val |= (step & AR933X_UART_CLK_STEP_M) + << AR933X_UART_CLK_STEP_S; + writel(val, priv->regs + AR933X_UART_CLK_REG); + + return 0; +} + +static int ar933x_serial_putc(struct udevice *dev, const char c) +{ + struct ar933x_serial_priv *priv = dev_get_priv(dev); + u32 data; + + data = readl(priv->regs + AR933X_UART_DATA_REG); + if (!(data & AR933X_UART_DATA_TX_CSR)) + return -EAGAIN; + + data = (u32)c | AR933X_UART_DATA_TX_CSR; + writel(data, priv->regs + AR933X_UART_DATA_REG); + + return 0; +} + +static int ar933x_serial_getc(struct udevice *dev) +{ + struct ar933x_serial_priv *priv = dev_get_priv(dev); + u32 data; + + data = readl(priv->regs + AR933X_UART_DATA_REG); + if (!(data & AR933X_UART_DATA_RX_CSR)) + return -EAGAIN; + + writel(AR933X_UART_DATA_RX_CSR, priv->regs + AR933X_UART_DATA_REG); + return data & AR933X_UART_DATA_TX_RX_MASK; +} + +static int ar933x_serial_pending(struct udevice *dev, bool input) +{ + struct ar933x_serial_priv *priv = dev_get_priv(dev); + u32 data; + + data = readl(priv->regs + AR933X_UART_DATA_REG); + if (input) + return (data & AR933X_UART_DATA_RX_CSR) ? 1 : 0; + else + return (data & AR933X_UART_DATA_TX_CSR) ? 0 : 1; +} + +static int ar933x_serial_probe(struct udevice *dev) +{ + struct ar933x_serial_priv *priv = dev_get_priv(dev); + struct udevice *pinctrl; + fdt_addr_t addr; + u32 val; + int ret; + + ret = uclass_get_device(UCLASS_PINCTRL, 0, &pinctrl); + if (ret) + return ret; + ret = pinctrl_get_periph_id(pinctrl, dev); + if (ret < 0) + return ret; + ret = pinctrl_request(pinctrl, ret, 0); + if (ret < 0) + return ret; + + addr = dev_get_addr(dev); + if (addr == FDT_ADDR_T_NONE) + return -EINVAL; + + priv->regs = map_physmem(addr, + AR933X_UART_SIZE, + MAP_NOCACHE); + + /* + * UART controller configuration: + * - no DMA + * - no interrupt + * - DCE mode + * - no flow control + * - set RX ready oride + * - set TX ready oride + */ + val = (AR933X_UART_CS_IF_MODE_DCE << AR933X_UART_CS_IF_MODE_S) | + AR933X_UART_CS_TX_RDY_ORIDE | AR933X_UART_CS_RX_RDY_ORIDE; + writel(val, priv->regs + AR933X_UART_CS_REG); + return 0; +} + +static const struct dm_serial_ops ar933x_serial_ops = { + .putc = ar933x_serial_putc, + .pending = ar933x_serial_pending, + .getc = ar933x_serial_getc, + .setbrg = ar933x_serial_setbrg, +}; + +static const struct udevice_id ar933x_serial_ids[] = { + { .compatible = "qca,ar9330-uart" }, + { } +}; + +U_BOOT_DRIVER(serial_ar933x) = { + .name = "serial_ar933x", + .id = UCLASS_SERIAL, + .of_match = ar933x_serial_ids, + .priv_auto_alloc_size = sizeof(struct ar933x_serial_priv), + .probe = ar933x_serial_probe, + .ops = &ar933x_serial_ops, + .flags = DM_FLAG_PRE_RELOC, +}; + +#ifdef CONFIG_DEBUG_UART_AR933X + +#include + +static inline void _debug_uart_init(void) +{ + void __iomem *regs = (void *)CONFIG_DEBUG_UART_BASE; + u32 val, scale, step; + + /* + * UART controller configuration: + * - no DMA + * - no interrupt + * - DCE mode + * - no flow control + * - set RX ready oride + * - set TX ready oride + */ + val = (AR933X_UART_CS_IF_MODE_DCE << AR933X_UART_CS_IF_MODE_S) | + AR933X_UART_CS_TX_RDY_ORIDE | AR933X_UART_CS_RX_RDY_ORIDE; + writel(val, regs + AR933X_UART_CS_REG); + + ar933x_serial_get_scale_step(CONFIG_DEBUG_UART_CLOCK, + CONFIG_BAUDRATE, &scale, &step); + + val = (scale & AR933X_UART_CLK_SCALE_M) + << AR933X_UART_CLK_SCALE_S; + val |= (step & AR933X_UART_CLK_STEP_M) + << AR933X_UART_CLK_STEP_S; + writel(val, regs + AR933X_UART_CLK_REG); +} + +static inline void _debug_uart_putc(int c) +{ + void __iomem *regs = (void *)CONFIG_DEBUG_UART_BASE; + u32 data; + + do { + data = readl(regs + AR933X_UART_DATA_REG); + } while (!(data & AR933X_UART_DATA_TX_CSR)); + + data = (u32)c | AR933X_UART_DATA_TX_CSR; + writel(data, regs + AR933X_UART_DATA_REG); +} + +DEBUG_UART_FUNCS + +#endif From b85dc4607268ffc49af642ab702d44c8b5ef3719 Mon Sep 17 00:00:00 2001 From: Wills Wang Date: Wed, 16 Mar 2016 16:59:58 +0800 Subject: [PATCH 126/162] drivers: spi: add spi support for QCA/Atheros ath79 SOCs This patch add a compatible spi driver for ath79 series SOC. Signed-off-by: Wills Wang Reviewed-by: Thomas Chou Reviewed-by: Daniel Schwierzeck --- doc/device-tree-bindings/spi/spi-ath79.txt | 19 ++ drivers/spi/Kconfig | 9 + drivers/spi/Makefile | 1 + drivers/spi/ath79_spi.c | 240 +++++++++++++++++++++ 4 files changed, 269 insertions(+) create mode 100644 doc/device-tree-bindings/spi/spi-ath79.txt create mode 100644 drivers/spi/ath79_spi.c diff --git a/doc/device-tree-bindings/spi/spi-ath79.txt b/doc/device-tree-bindings/spi/spi-ath79.txt new file mode 100644 index 0000000000..3fd9d67a2b --- /dev/null +++ b/doc/device-tree-bindings/spi/spi-ath79.txt @@ -0,0 +1,19 @@ +Binding for Qualcomm Atheros AR7xxx/AR9xxx SPI controller + +Required properties: +- compatible: has to be "qca,-spi", "qca,ar7100-spi" as fallback. +- reg: Base address and size of the controllers memory area +- #address-cells: <1>, as required by generic SPI binding. +- #size-cells: <0>, also as required by generic SPI binding. + +Child nodes as per the generic SPI binding. + +Example: + + spi@1f000000 { + compatible = "qca,ar9132-spi", "qca,ar7100-spi"; + reg = <0x1f000000 0x10>; + + #address-cells = <1>; + #size-cells = <0>; + }; diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index f0258f84af..b7fd8e53a2 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -23,6 +23,15 @@ config ALTERA_SPI IP core. Please find details on the "Embedded Peripherals IP User Guide" of Altera. +config ATH79_SPI + bool "Atheros SPI driver" + depends on ARCH_ATH79 + help + Enable the Atheros ar7xxx/ar9xxx SoC SPI driver, it was used + to access SPI NOR flash and other SPI peripherals. This driver + uses driver model and requires a device tree binding to operate. + please refer to doc/device-tree-bindings/spi/spi-ath79.txt. + config CADENCE_QSPI bool "Cadence QSPI driver" help diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile index 3eca7456d6..7fb2926e78 100644 --- a/drivers/spi/Makefile +++ b/drivers/spi/Makefile @@ -17,6 +17,7 @@ endif obj-$(CONFIG_ALTERA_SPI) += altera_spi.o obj-$(CONFIG_ARMADA100_SPI) += armada100_spi.o +obj-$(CONFIG_ATH79_SPI) += ath79_spi.o obj-$(CONFIG_ATMEL_DATAFLASH_SPI) += atmel_dataflash_spi.o obj-$(CONFIG_ATMEL_SPI) += atmel_spi.o obj-$(CONFIG_BFIN_SPI) += bfin_spi.o diff --git a/drivers/spi/ath79_spi.c b/drivers/spi/ath79_spi.c new file mode 100644 index 0000000000..0c1022da05 --- /dev/null +++ b/drivers/spi/ath79_spi.c @@ -0,0 +1,240 @@ +/* + * Copyright (C) 2015-2016 Wills Wang + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* CLOCK_DIVIDER = 3 (SPI clock = 200 / 8 ~ 25 MHz) */ +#define ATH79_SPI_CLK_DIV(x) (((x) >> 1) - 1) +#define ATH79_SPI_RRW_DELAY_FACTOR 12000 +#define ATH79_SPI_MHZ (1000 * 1000) + +struct ath79_spi_priv { + void __iomem *regs; + u32 rrw_delay; +}; + +static void spi_cs_activate(struct udevice *dev) +{ + struct udevice *bus = dev_get_parent(dev); + struct ath79_spi_priv *priv = dev_get_priv(bus); + + writel(AR71XX_SPI_FS_GPIO, priv->regs + AR71XX_SPI_REG_FS); + writel(AR71XX_SPI_IOC_CS_ALL, priv->regs + AR71XX_SPI_REG_IOC); +} + +static void spi_cs_deactivate(struct udevice *dev) +{ + struct udevice *bus = dev_get_parent(dev); + struct ath79_spi_priv *priv = dev_get_priv(bus); + + writel(AR71XX_SPI_IOC_CS_ALL, priv->regs + AR71XX_SPI_REG_IOC); + writel(0, priv->regs + AR71XX_SPI_REG_FS); +} + +static int ath79_spi_claim_bus(struct udevice *dev) +{ + return 0; +} + +static int ath79_spi_release_bus(struct udevice *dev) +{ + return 0; +} + +static int ath79_spi_xfer(struct udevice *dev, unsigned int bitlen, + const void *dout, void *din, unsigned long flags) +{ + struct udevice *bus = dev_get_parent(dev); + struct ath79_spi_priv *priv = dev_get_priv(bus); + struct dm_spi_slave_platdata *slave = dev_get_parent_platdata(dev); + u8 *rx = din; + const u8 *tx = dout; + u8 curbyte, curbitlen, restbits; + u32 bytes = bitlen / 8; + u32 out, in; + u64 tick; + + if (flags & SPI_XFER_BEGIN) + spi_cs_activate(dev); + + restbits = (bitlen % 8); + if (restbits) + bytes++; + + out = AR71XX_SPI_IOC_CS_ALL & ~(AR71XX_SPI_IOC_CS(slave->cs)); + while (bytes > 0) { + bytes--; + curbyte = 0; + if (tx) + curbyte = *tx++; + + if (restbits && !bytes) { + curbitlen = restbits; + curbyte <<= 8 - restbits; + } else { + curbitlen = 8; + } + + for (curbyte <<= (8 - curbitlen); curbitlen; curbitlen--) { + if (curbyte & 0x80) + out |= AR71XX_SPI_IOC_DO; + else + out &= ~(AR71XX_SPI_IOC_DO); + + writel(out, priv->regs + AR71XX_SPI_REG_IOC); + + /* delay for low level */ + if (priv->rrw_delay) { + tick = get_ticks() + priv->rrw_delay; + while (get_ticks() < tick) + /*NOP*/; + } + + writel(out | AR71XX_SPI_IOC_CLK, + priv->regs + AR71XX_SPI_REG_IOC); + + /* delay for high level */ + if (priv->rrw_delay) { + tick = get_ticks() + priv->rrw_delay; + while (get_ticks() < tick) + /*NOP*/; + } + + curbyte <<= 1; + } + + if (!bytes) + writel(out, priv->regs + AR71XX_SPI_REG_IOC); + + in = readl(priv->regs + AR71XX_SPI_REG_RDS); + if (rx) { + if (restbits && !bytes) + *rx++ = (in << (8 - restbits)); + else + *rx++ = in; + } + } + + if (flags & SPI_XFER_END) + spi_cs_deactivate(dev); + + return 0; +} + + +static int ath79_spi_set_speed(struct udevice *bus, uint speed) +{ + struct ath79_spi_priv *priv = dev_get_priv(bus); + u32 val, div = 0; + u64 time; + + if (speed) + div = get_bus_freq(0) / speed; + + if (div > 63) + div = 63; + + if (div < 5) + div = 5; + + /* calculate delay */ + time = get_tbclk(); + do_div(time, speed / 2); + val = get_bus_freq(0) / ATH79_SPI_MHZ; + val = ATH79_SPI_RRW_DELAY_FACTOR / val; + if (time > val) + priv->rrw_delay = time - val + 1; + else + priv->rrw_delay = 0; + + writel(AR71XX_SPI_FS_GPIO, priv->regs + AR71XX_SPI_REG_FS); + clrsetbits_be32(priv->regs + AR71XX_SPI_REG_CTRL, + AR71XX_SPI_CTRL_DIV_MASK, + ATH79_SPI_CLK_DIV(div)); + writel(0, priv->regs + AR71XX_SPI_REG_FS); + return 0; +} + +static int ath79_spi_set_mode(struct udevice *bus, uint mode) +{ + return 0; +} + +static int ath79_spi_probe(struct udevice *bus) +{ + struct ath79_spi_priv *priv = dev_get_priv(bus); + struct udevice *pinctrl; + fdt_addr_t addr; + int ret; + + ret = uclass_get_device(UCLASS_PINCTRL, 0, &pinctrl); + if (ret) + return ret; + ret = pinctrl_get_periph_id(pinctrl, bus); + if (ret < 0) + return ret; + ret = pinctrl_request(pinctrl, ret, 0); + if (ret < 0) + return ret; + + addr = dev_get_addr(bus); + if (addr == FDT_ADDR_T_NONE) + return -EINVAL; + + priv->regs = map_physmem(addr, + AR71XX_SPI_SIZE, + MAP_NOCACHE); + + /* Init SPI Hardware, disable remap, set clock */ + writel(AR71XX_SPI_FS_GPIO, priv->regs + AR71XX_SPI_REG_FS); + writel(AR71XX_SPI_CTRL_RD | ATH79_SPI_CLK_DIV(8), + priv->regs + AR71XX_SPI_REG_CTRL); + writel(0, priv->regs + AR71XX_SPI_REG_FS); + + return 0; +} + +static int ath79_cs_info(struct udevice *bus, uint cs, + struct spi_cs_info *info) +{ + /* Always allow activity on CS 0/1/2 */ + if (cs >= 3) + return -ENODEV; + + return 0; +} + +static const struct dm_spi_ops ath79_spi_ops = { + .claim_bus = ath79_spi_claim_bus, + .release_bus = ath79_spi_release_bus, + .xfer = ath79_spi_xfer, + .set_speed = ath79_spi_set_speed, + .set_mode = ath79_spi_set_mode, + .cs_info = ath79_cs_info, +}; + +static const struct udevice_id ath79_spi_ids[] = { + { .compatible = "qca,ar7100-spi" }, + {} +}; + +U_BOOT_DRIVER(ath79_spi) = { + .name = "ath79_spi", + .id = UCLASS_SPI, + .of_match = ath79_spi_ids, + .ops = &ath79_spi_ops, + .priv_auto_alloc_size = sizeof(struct ath79_spi_priv), + .probe = ath79_spi_probe, +}; From 6a7b52bc8d30090633d098f9e988276beb7a53d5 Mon Sep 17 00:00:00 2001 From: Wills Wang Date: Wed, 16 Mar 2016 16:59:59 +0800 Subject: [PATCH 127/162] mips: ath79: add AP121 reference board This patch add board-level code and base DT for AP121. Signed-off-by: Wills Wang [updated defconfig, enabled CONFIG_USE_PRIVATE_LIBGCC=y] Signed-off-by: Daniel Schwierzeck --- arch/mips/dts/Makefile | 1 + arch/mips/dts/ap121.dts | 43 ++++++++++++++++++ arch/mips/dts/ar933x.dtsi | 82 ++++++++++++++++++++++++++++++++++ arch/mips/mach-ath79/Kconfig | 11 +++++ board/qca/ap121/Kconfig | 12 +++++ board/qca/ap121/MAINTAINERS | 6 +++ board/qca/ap121/Makefile | 5 +++ board/qca/ap121/ap121.c | 50 +++++++++++++++++++++ configs/ap121_defconfig | 47 ++++++++++++++++++++ include/configs/ap121.h | 86 ++++++++++++++++++++++++++++++++++++ 10 files changed, 343 insertions(+) create mode 100644 arch/mips/dts/ap121.dts create mode 100644 arch/mips/dts/ar933x.dtsi create mode 100644 board/qca/ap121/Kconfig create mode 100644 board/qca/ap121/MAINTAINERS create mode 100644 board/qca/ap121/Makefile create mode 100644 board/qca/ap121/ap121.c create mode 100644 configs/ap121_defconfig create mode 100644 include/configs/ap121.h diff --git a/arch/mips/dts/Makefile b/arch/mips/dts/Makefile index b5139187c2..30e5c6871a 100644 --- a/arch/mips/dts/Makefile +++ b/arch/mips/dts/Makefile @@ -2,6 +2,7 @@ # SPDX-License-Identifier: GPL-2.0+ # +dtb-$(CONFIG_TARGET_AP121) += ap121.dtb dtb-$(CONFIG_TARGET_PIC32MZDASK) += pic32mzda_sk.dtb targets += $(dtb-y) diff --git a/arch/mips/dts/ap121.dts b/arch/mips/dts/ap121.dts new file mode 100644 index 0000000000..e31f601d03 --- /dev/null +++ b/arch/mips/dts/ap121.dts @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2015-2016 Wills Wang + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +/dts-v1/; +#include "ar933x.dtsi" + +/ { + model = "AP121 Reference Board"; + compatible = "qca,ap121", "qca,ar933x"; + + aliases { + spi0 = &spi0; + serial0 = &uart0; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; +}; + +&xtal { + clock-frequency = <25000000>; +}; + +&uart0 { + status = "okay"; +}; + +&spi0 { + spi-max-frequency = <25000000>; + status = "okay"; + spi-flash@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "spi-flash"; + memory-map = <0x9f000000 0x00800000>; + spi-max-frequency = <25000000>; + reg = <0>; + }; +}; diff --git a/arch/mips/dts/ar933x.dtsi b/arch/mips/dts/ar933x.dtsi new file mode 100644 index 0000000000..11f60a2864 --- /dev/null +++ b/arch/mips/dts/ar933x.dtsi @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2015-2016 Wills Wang + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include "skeleton.dtsi" + +/ { + compatible = "qca,ar933x"; + + #address-cells = <1>; + #size-cells = <1>; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + + cpu@0 { + device_type = "cpu"; + compatible = "mips,mips24Kc"; + reg = <0>; + }; + }; + + clocks { + #address-cells = <1>; + #size-cells = <1>; + ranges; + + xtal: xtal { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-output-names = "xtal"; + }; + }; + + pinctrl { + u-boot,dm-pre-reloc; + compatible = "qca,ar933x-pinctrl"; + ranges; + #address-cells = <1>; + #size-cells = <1>; + reg = <0x18040000 0x100>; + }; + + ahb { + compatible = "simple-bus"; + ranges; + + #address-cells = <1>; + #size-cells = <1>; + + apb { + compatible = "simple-bus"; + ranges; + + #address-cells = <1>; + #size-cells = <1>; + + uart0: uart@18020000 { + compatible = "qca,ar9330-uart"; + reg = <0x18020000 0x20>; + interrupts = <128 IRQ_TYPE_LEVEL_HIGH>; + + status = "disabled"; + }; + }; + + spi0: spi@1f000000 { + compatible = "qca,ar7100-spi"; + reg = <0x1f000000 0x10>; + interrupts = <129 IRQ_TYPE_LEVEL_HIGH>; + + status = "disabled"; + + #address-cells = <1>; + #size-cells = <0>; + }; + }; +}; diff --git a/arch/mips/mach-ath79/Kconfig b/arch/mips/mach-ath79/Kconfig index e35f1b578f..c3012f8b53 100644 --- a/arch/mips/mach-ath79/Kconfig +++ b/arch/mips/mach-ath79/Kconfig @@ -22,4 +22,15 @@ config SOC_QCA953X help This supports QCA/Atheros qca953x family SOCs. +choice + prompt "Board select" + +config TARGET_AP121 + bool "AP121 Reference Board" + select SOC_AR933X + +endchoice + +source "board/qca/ap121/Kconfig" + endmenu diff --git a/board/qca/ap121/Kconfig b/board/qca/ap121/Kconfig new file mode 100644 index 0000000000..f7e768ad58 --- /dev/null +++ b/board/qca/ap121/Kconfig @@ -0,0 +1,12 @@ +if TARGET_AP121 + +config SYS_VENDOR + default "qca" + +config SYS_BOARD + default "ap121" + +config SYS_CONFIG_NAME + default "ap121" + +endif diff --git a/board/qca/ap121/MAINTAINERS b/board/qca/ap121/MAINTAINERS new file mode 100644 index 0000000000..8b02988d60 --- /dev/null +++ b/board/qca/ap121/MAINTAINERS @@ -0,0 +1,6 @@ +AP121 BOARD +M: Wills Wang +S: Maintained +F: board/qca/ap121/ +F: include/configs/ap121.h +F: configs/ap121_defconfig diff --git a/board/qca/ap121/Makefile b/board/qca/ap121/Makefile new file mode 100644 index 0000000000..ced5432e86 --- /dev/null +++ b/board/qca/ap121/Makefile @@ -0,0 +1,5 @@ +# +# SPDX-License-Identifier: GPL-2.0+ +# + +obj-y = ap121.o diff --git a/board/qca/ap121/ap121.c b/board/qca/ap121/ap121.c new file mode 100644 index 0000000000..d6c60fea86 --- /dev/null +++ b/board/qca/ap121/ap121.c @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2015-2016 Wills Wang + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include +#include +#include +#include + +DECLARE_GLOBAL_DATA_PTR; + +#ifdef CONFIG_DEBUG_UART_BOARD_INIT +void board_debug_uart_init(void) +{ + void __iomem *regs; + u32 val; + + regs = map_physmem(AR71XX_GPIO_BASE, AR71XX_GPIO_SIZE, + MAP_NOCACHE); + + /* + * GPIO9 as input, GPIO10 as output + */ + val = readl(regs + AR71XX_GPIO_REG_OE); + val &= ~AR933X_GPIO(9); + val |= AR933X_GPIO(10); + writel(val, regs + AR71XX_GPIO_REG_OE); + + /* + * Enable UART, GPIO9 as UART_SI, GPIO10 as UART_SO + */ + val = readl(regs + AR71XX_GPIO_REG_FUNC); + val |= AR933X_GPIO_FUNC_UART_EN | AR933X_GPIO_FUNC_RES_TRUE; + writel(val, regs + AR71XX_GPIO_REG_FUNC); +} +#endif + +int board_early_init_f(void) +{ +#ifdef CONFIG_DEBUG_UART + debug_uart_init(); +#endif + ddr_init(); + return 0; +} diff --git a/configs/ap121_defconfig b/configs/ap121_defconfig new file mode 100644 index 0000000000..7604e2ee16 --- /dev/null +++ b/configs/ap121_defconfig @@ -0,0 +1,47 @@ +CONFIG_MIPS=y +CONFIG_SYS_MALLOC_F_LEN=0x2000 +CONFIG_DM_SERIAL=y +CONFIG_DM_SPI=y +CONFIG_DM_SPI_FLASH=y +CONFIG_ARCH_ATH79=y +CONFIG_DEFAULT_DEVICE_TREE="ap121" +CONFIG_SYS_PROMPT="ap121 # " +# CONFIG_CMD_BDI is not set +# CONFIG_CMD_CONSOLE is not set +# CONFIG_CMD_ELF is not set +# CONFIG_CMD_IMLS is not set +# CONFIG_CMD_XIMG is not set +# CONFIG_CMD_EXPORTENV is not set +# CONFIG_CMD_IMPORTENV is not set +# CONFIG_CMD_EDITENV is not set +# CONFIG_CMD_CRC32 is not set +# CONFIG_CMD_FLASH is not set +CONFIG_CMD_SF=y +CONFIG_CMD_SPI=y +# CONFIG_CMD_FPGA is not set +# CONFIG_CMD_NET is not set +# CONFIG_CMD_NFS is not set +CONFIG_SPI_FLASH=y +CONFIG_SPI_FLASH_BAR=y +CONFIG_SPI_FLASH_ATMEL=y +CONFIG_SPI_FLASH_EON=y +CONFIG_SPI_FLASH_GIGADEVICE=y +CONFIG_SPI_FLASH_MACRONIX=y +CONFIG_SPI_FLASH_SPANSION=y +CONFIG_SPI_FLASH_STMICRO=y +CONFIG_SPI_FLASH_SST=y +CONFIG_SPI_FLASH_WINBOND=y +CONFIG_SPI_FLASH_DATAFLASH=y +CONFIG_SPI_FLASH_MTD=y +CONFIG_PINCTRL=y +CONFIG_PINCONF=y +CONFIG_AR933X_PINCTRL=y +CONFIG_DEBUG_UART=y +CONFIG_DEBUG_UART_AR933X=y +CONFIG_DEBUG_UART_BASE=0xb8020000 +CONFIG_DEBUG_UART_CLOCK=25000000 +CONFIG_DEBUG_UART_BOARD_INIT=y +CONFIG_AR933X_UART=y +CONFIG_ATH79_SPI=y +CONFIG_USE_PRIVATE_LIBGCC=y +CONFIG_OF_LIBFDT=y diff --git a/include/configs/ap121.h b/include/configs/ap121.h new file mode 100644 index 0000000000..2beffa4805 --- /dev/null +++ b/include/configs/ap121.h @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2015-2016 Wills Wang + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef __CONFIG_H +#define __CONFIG_H + +#define CONFIG_SYS_TEXT_BASE 0x9f000000 + +#define CONFIG_DISPLAY_CPUINFO +#define CONFIG_DISPLAY_BOARDINFO +#define CONFIG_BOARD_EARLY_INIT_F + +#define CONFIG_SYS_HZ 1000 +#define CONFIG_SYS_MHZ 200 +#define CONFIG_SYS_MIPS_TIMER_FREQ (CONFIG_SYS_MHZ * 1000000) + +/* Cache Configuration */ +#define CONFIG_SYS_DCACHE_SIZE 0x8000 +#define CONFIG_SYS_ICACHE_SIZE 0x10000 +#define CONFIG_SYS_CACHELINE_SIZE 32 + +#define CONFIG_SYS_MONITOR_BASE CONFIG_SYS_TEXT_BASE + +#define CONFIG_SYS_MALLOC_LEN 0x40000 +#define CONFIG_SYS_BOOTPARAMS_LEN 0x20000 + +#define CONFIG_SYS_SDRAM_BASE 0x80000000 +#define CONFIG_SYS_LOAD_ADDR 0x81000000 + +#define CONFIG_SYS_NO_FLASH + +#define CONFIG_SYS_INIT_RAM_ADDR 0xbd000000 +#define CONFIG_SYS_INIT_RAM_SIZE 0x8000 +#define CONFIG_SYS_INIT_SP_ADDR \ + (CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_INIT_RAM_SIZE - 1) + +#define CONFIG_BAUDRATE 115200 +#define CONFIG_SYS_BAUDRATE_TABLE \ + {9600, 19200, 38400, 57600, 115200} + +#define CONFIG_BOOTDELAY 3 +#define CONFIG_BOOTARGS "console=ttyS0,115200 " \ + "root=/dev/mtdblock2 " \ + "rootfstype=squashfs" +#define CONFIG_BOOTCOMMAND "sf probe;" \ + "mtdparts default;" \ + "bootm 0x9f300000" +#define CONFIG_LZMA + +#define MTDIDS_DEFAULT "nor0=spi-flash.0" +#define MTDPARTS_DEFAULT "mtdparts=spi-flash.0:" \ + "256k(u-boot),64k(u-boot-env)," \ + "2752k(rootfs),896k(uImage)," \ + "64k(NVRAM),64k(ART)" + +#define CONFIG_ENV_SPI_MAX_HZ 25000000 +#define CONFIG_ENV_IS_IN_SPI_FLASH +#define CONFIG_ENV_OFFSET 0x40000 +#define CONFIG_ENV_SECT_SIZE 0x10000 +#define CONFIG_ENV_SIZE 0x10000 + +/* + * Command + */ +#define CONFIG_CMD_MTDPARTS + +/* Miscellaneous configurable options */ +#define CONFIG_SYS_CBSIZE 256 +#define CONFIG_SYS_MAXARGS 16 +#define CONFIG_SYS_PBSIZE (CONFIG_SYS_CBSIZE + \ + sizeof(CONFIG_SYS_PROMPT) + 16) +#define CONFIG_SYS_LONGHELP +#define CONFIG_CMDLINE_EDITING +#define CONFIG_AUTO_COMPLETE + +/* + * Diagnostics + */ +#define CONFIG_SYS_MEMTEST_START 0x80100000 +#define CONFIG_SYS_MEMTEST_END 0x83f00000 +#define CONFIG_CMD_MEMTEST + +#endif /* __CONFIG_H */ From a2277cc30cdb40298aca80344f3764db6a0cfb8d Mon Sep 17 00:00:00 2001 From: Wills Wang Date: Wed, 16 Mar 2016 17:00:00 +0800 Subject: [PATCH 128/162] mips: ath79: add AP143 reference board This patch add board-level code and base DT for AP143. Signed-off-by: Wills Wang [updated defconfig, enabled CONFIG_USE_PRIVATE_LIBGCC=y] Signed-off-by: Daniel Schwierzeck --- arch/mips/dts/Makefile | 1 + arch/mips/dts/ap143.dts | 43 +++++++++++++++++ arch/mips/dts/qca953x.dtsi | 84 +++++++++++++++++++++++++++++++++ arch/mips/mach-ath79/Kconfig | 5 ++ board/qca/ap143/Kconfig | 12 +++++ board/qca/ap143/MAINTAINERS | 6 +++ board/qca/ap143/Makefile | 5 ++ board/qca/ap143/ap143.c | 66 ++++++++++++++++++++++++++ configs/ap143_defconfig | 47 +++++++++++++++++++ include/configs/ap143.h | 90 ++++++++++++++++++++++++++++++++++++ 10 files changed, 359 insertions(+) create mode 100644 arch/mips/dts/ap143.dts create mode 100644 arch/mips/dts/qca953x.dtsi create mode 100644 board/qca/ap143/Kconfig create mode 100644 board/qca/ap143/MAINTAINERS create mode 100644 board/qca/ap143/Makefile create mode 100644 board/qca/ap143/ap143.c create mode 100644 configs/ap143_defconfig create mode 100644 include/configs/ap143.h diff --git a/arch/mips/dts/Makefile b/arch/mips/dts/Makefile index 30e5c6871a..bd87ead972 100644 --- a/arch/mips/dts/Makefile +++ b/arch/mips/dts/Makefile @@ -3,6 +3,7 @@ # dtb-$(CONFIG_TARGET_AP121) += ap121.dtb +dtb-$(CONFIG_TARGET_AP143) += ap143.dtb dtb-$(CONFIG_TARGET_PIC32MZDASK) += pic32mzda_sk.dtb targets += $(dtb-y) diff --git a/arch/mips/dts/ap143.dts b/arch/mips/dts/ap143.dts new file mode 100644 index 0000000000..f53207e771 --- /dev/null +++ b/arch/mips/dts/ap143.dts @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2015-2016 Wills Wang + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +/dts-v1/; +#include "qca953x.dtsi" + +/ { + model = "AP143 Reference Board"; + compatible = "qca,ap143", "qca,qca953x"; + + aliases { + spi0 = &spi0; + serial0 = &uart0; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; +}; + +&xtal { + clock-frequency = <25000000>; +}; + +&uart0 { + status = "okay"; +}; + +&spi0 { + spi-max-frequency = <25000000>; + status = "okay"; + spi-flash@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "spi-flash"; + memory-map = <0x9f000000 0x00800000>; + spi-max-frequency = <25000000>; + reg = <0>; + }; +}; diff --git a/arch/mips/dts/qca953x.dtsi b/arch/mips/dts/qca953x.dtsi new file mode 100644 index 0000000000..870010f0e4 --- /dev/null +++ b/arch/mips/dts/qca953x.dtsi @@ -0,0 +1,84 @@ +/* + * Copyright (C) 2015-2016 Wills Wang + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include "skeleton.dtsi" + +/ { + compatible = "qca,qca953x"; + + #address-cells = <1>; + #size-cells = <1>; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + + cpu@0 { + device_type = "cpu"; + compatible = "mips,mips24Kc"; + reg = <0>; + }; + }; + + clocks { + #address-cells = <1>; + #size-cells = <1>; + ranges; + + xtal: xtal { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-output-names = "xtal"; + }; + }; + + pinctrl { + u-boot,dm-pre-reloc; + compatible = "qca,qca953x-pinctrl"; + ranges; + #address-cells = <1>; + #size-cells = <1>; + reg = <0x18040000 0x100>; + }; + + ahb { + compatible = "simple-bus"; + ranges; + + #address-cells = <1>; + #size-cells = <1>; + + apb { + compatible = "simple-bus"; + ranges; + + #address-cells = <1>; + #size-cells = <1>; + + uart0: uart@18020000 { + compatible = "ns16550"; + reg = <0x18020000 0x20>; + reg-shift = <2>; + clock-frequency = <25000000>; + interrupts = <128 IRQ_TYPE_LEVEL_HIGH>; + + status = "disabled"; + }; + }; + + spi0: spi@1f000000 { + compatible = "qca,ar7100-spi"; + reg = <0x1f000000 0x10>; + interrupts = <129 IRQ_TYPE_LEVEL_HIGH>; + + status = "disabled"; + + #address-cells = <1>; + #size-cells = <0>; + }; + }; +}; diff --git a/arch/mips/mach-ath79/Kconfig b/arch/mips/mach-ath79/Kconfig index c3012f8b53..f45403bda9 100644 --- a/arch/mips/mach-ath79/Kconfig +++ b/arch/mips/mach-ath79/Kconfig @@ -29,8 +29,13 @@ config TARGET_AP121 bool "AP121 Reference Board" select SOC_AR933X +config TARGET_AP143 + bool "AP143 Reference Board" + select SOC_QCA953X + endchoice source "board/qca/ap121/Kconfig" +source "board/qca/ap143/Kconfig" endmenu diff --git a/board/qca/ap143/Kconfig b/board/qca/ap143/Kconfig new file mode 100644 index 0000000000..4cdac0d06d --- /dev/null +++ b/board/qca/ap143/Kconfig @@ -0,0 +1,12 @@ +if TARGET_AP143 + +config SYS_VENDOR + default "qca" + +config SYS_BOARD + default "ap143" + +config SYS_CONFIG_NAME + default "ap143" + +endif diff --git a/board/qca/ap143/MAINTAINERS b/board/qca/ap143/MAINTAINERS new file mode 100644 index 0000000000..11cb14fc74 --- /dev/null +++ b/board/qca/ap143/MAINTAINERS @@ -0,0 +1,6 @@ +AP143 BOARD +M: Wills Wang +S: Maintained +F: board/qca/ap143/ +F: include/configs/ap143.h +F: configs/ap143_defconfig diff --git a/board/qca/ap143/Makefile b/board/qca/ap143/Makefile new file mode 100644 index 0000000000..00f78376ec --- /dev/null +++ b/board/qca/ap143/Makefile @@ -0,0 +1,5 @@ +# +# SPDX-License-Identifier: GPL-2.0+ +# + +obj-y = ap143.o diff --git a/board/qca/ap143/ap143.c b/board/qca/ap143/ap143.c new file mode 100644 index 0000000000..1572472ca3 --- /dev/null +++ b/board/qca/ap143/ap143.c @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2015-2016 Wills Wang + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include +#include +#include +#include + +DECLARE_GLOBAL_DATA_PTR; + +#ifdef CONFIG_DEBUG_UART_BOARD_INIT +void board_debug_uart_init(void) +{ + void __iomem *regs; + u32 val; + + regs = map_physmem(AR71XX_GPIO_BASE, AR71XX_GPIO_SIZE, + MAP_NOCACHE); + + /* + * GPIO9 as input, GPIO10 as output + */ + val = readl(regs + AR71XX_GPIO_REG_OE); + val |= QCA953X_GPIO(9); + val &= ~QCA953X_GPIO(10); + writel(val, regs + AR71XX_GPIO_REG_OE); + + /* + * Enable GPIO10 as UART0_SOUT + */ + val = readl(regs + QCA953X_GPIO_REG_OUT_FUNC2); + val &= ~QCA953X_GPIO_MUX_MASK(16); + val |= QCA953X_GPIO_OUT_MUX_UART0_SOUT << 16; + writel(val, regs + QCA953X_GPIO_REG_OUT_FUNC2); + + /* + * Enable GPIO9 as UART0_SIN + */ + val = readl(regs + QCA953X_GPIO_REG_IN_ENABLE0); + val &= ~QCA953X_GPIO_MUX_MASK(8); + val |= QCA953X_GPIO_IN_MUX_UART0_SIN << 8; + writel(val, regs + QCA953X_GPIO_REG_IN_ENABLE0); + + /* + * Enable GPIO10 output + */ + val = readl(regs + AR71XX_GPIO_REG_OUT); + val |= QCA953X_GPIO(10); + writel(val, regs + AR71XX_GPIO_REG_OUT); +} +#endif + +int board_early_init_f(void) +{ +#ifdef CONFIG_DEBUG_UART + debug_uart_init(); +#endif + ddr_init(); + return 0; +} diff --git a/configs/ap143_defconfig b/configs/ap143_defconfig new file mode 100644 index 0000000000..1aa6e5d7ab --- /dev/null +++ b/configs/ap143_defconfig @@ -0,0 +1,47 @@ +CONFIG_MIPS=y +CONFIG_SYS_MALLOC_F_LEN=0x800 +CONFIG_DM_SERIAL=y +CONFIG_DM_SPI=y +CONFIG_DM_SPI_FLASH=y +CONFIG_ARCH_ATH79=y +CONFIG_TARGET_AP143=y +CONFIG_DEFAULT_DEVICE_TREE="ap143" +CONFIG_SYS_PROMPT="ap143 # " +# CONFIG_CMD_BDI is not set +# CONFIG_CMD_CONSOLE is not set +# CONFIG_CMD_ELF is not set +# CONFIG_CMD_IMLS is not set +# CONFIG_CMD_XIMG is not set +# CONFIG_CMD_EXPORTENV is not set +# CONFIG_CMD_IMPORTENV is not set +# CONFIG_CMD_EDITENV is not set +# CONFIG_CMD_CRC32 is not set +# CONFIG_CMD_FLASH is not set +CONFIG_CMD_SF=y +CONFIG_CMD_SPI=y +# CONFIG_CMD_FPGA is not set +# CONFIG_CMD_NET is not set +# CONFIG_CMD_NFS is not set +CONFIG_SPI_FLASH=y +CONFIG_SPI_FLASH_BAR=y +CONFIG_SPI_FLASH_ATMEL=y +CONFIG_SPI_FLASH_EON=y +CONFIG_SPI_FLASH_GIGADEVICE=y +CONFIG_SPI_FLASH_MACRONIX=y +CONFIG_SPI_FLASH_SPANSION=y +CONFIG_SPI_FLASH_STMICRO=y +CONFIG_SPI_FLASH_SST=y +CONFIG_SPI_FLASH_WINBOND=y +CONFIG_SPI_FLASH_DATAFLASH=y +CONFIG_SPI_FLASH_MTD=y +CONFIG_PINCTRL=y +CONFIG_QCA953X_PINCTRL=y +CONFIG_DEBUG_UART=y +CONFIG_DEBUG_UART_BASE=0xb8020000 +CONFIG_DEBUG_UART_CLOCK=25000000 +CONFIG_DEBUG_UART_SHIFT=2 +CONFIG_DEBUG_UART_BOARD_INIT=y +CONFIG_SYS_NS16550=y +CONFIG_ATH79_SPI=y +CONFIG_USE_PRIVATE_LIBGCC=y +CONFIG_OF_LIBFDT=y diff --git a/include/configs/ap143.h b/include/configs/ap143.h new file mode 100644 index 0000000000..7b69e10be4 --- /dev/null +++ b/include/configs/ap143.h @@ -0,0 +1,90 @@ +/* + * Copyright (C) 2015-2016 Wills Wang + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef __CONFIG_H +#define __CONFIG_H + +#define CONFIG_SYS_TEXT_BASE 0x9f000000 + +#define CONFIG_DISPLAY_CPUINFO +#define CONFIG_DISPLAY_BOARDINFO +#define CONFIG_BOARD_EARLY_INIT_F + +#define CONFIG_SYS_HZ 1000 +#define CONFIG_SYS_MHZ 325 +#define CONFIG_SYS_MIPS_TIMER_FREQ (CONFIG_SYS_MHZ * 1000000) + +/* Cache Configuration */ +#define CONFIG_SYS_DCACHE_SIZE 0x8000 +#define CONFIG_SYS_ICACHE_SIZE 0x10000 +#define CONFIG_SYS_CACHELINE_SIZE 32 + +#define CONFIG_SYS_MONITOR_BASE CONFIG_SYS_TEXT_BASE + +#define CONFIG_SYS_MALLOC_LEN 0x40000 +#define CONFIG_SYS_BOOTPARAMS_LEN 0x20000 + +#define CONFIG_SYS_SDRAM_BASE 0x80000000 +#define CONFIG_SYS_LOAD_ADDR 0x81000000 + +#define CONFIG_SYS_NO_FLASH + +#define CONFIG_SYS_INIT_RAM_ADDR 0xbd000000 +#define CONFIG_SYS_INIT_RAM_SIZE 0x2000 +#define CONFIG_SYS_INIT_SP_ADDR \ + (CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_INIT_RAM_SIZE - 1) + +/* + * Serial Port + */ +#define CONFIG_SYS_NS16550_CLK 25000000 +#define CONFIG_BAUDRATE 115200 +#define CONFIG_SYS_BAUDRATE_TABLE \ + {9600, 19200, 38400, 57600, 115200} + +#define CONFIG_BOOTDELAY 3 +#define CONFIG_BOOTARGS "console=ttyS0,115200 " \ + "root=/dev/mtdblock2 " \ + "rootfstype=squashfs" +#define CONFIG_BOOTCOMMAND "sf probe;" \ + "mtdparts default;" \ + "bootm 0x9f300000" +#define CONFIG_LZMA + +#define MTDIDS_DEFAULT "nor0=spi-flash.0" +#define MTDPARTS_DEFAULT "mtdparts=spi-flash.0:" \ + "256k(u-boot),64k(u-boot-env)," \ + "2752k(rootfs),896k(uImage)," \ + "64k(NVRAM),64k(ART)" + +#define CONFIG_ENV_SPI_MAX_HZ 25000000 +#define CONFIG_ENV_IS_IN_SPI_FLASH +#define CONFIG_ENV_OFFSET 0x40000 +#define CONFIG_ENV_SECT_SIZE 0x10000 +#define CONFIG_ENV_SIZE 0x10000 + +/* + * Command + */ +#define CONFIG_CMD_MTDPARTS + +/* Miscellaneous configurable options */ +#define CONFIG_SYS_CBSIZE 256 +#define CONFIG_SYS_MAXARGS 16 +#define CONFIG_SYS_PBSIZE (CONFIG_SYS_CBSIZE + \ + sizeof(CONFIG_SYS_PROMPT) + 16) +#define CONFIG_SYS_LONGHELP +#define CONFIG_CMDLINE_EDITING +#define CONFIG_AUTO_COMPLETE + +/* + * Diagnostics + */ +#define CONFIG_SYS_MEMTEST_START 0x80100000 +#define CONFIG_SYS_MEMTEST_END 0x83f00000 +#define CONFIG_CMD_MEMTEST + +#endif /* __CONFIG_H */ From 30fd42cba6e7d4147e2dd4e9dbe9728efbcd24fe Mon Sep 17 00:00:00 2001 From: Purna Chandra Mandal Date: Fri, 18 Mar 2016 18:36:07 +0530 Subject: [PATCH 129/162] flash: add device ID for Microchip PIC32 internal flash. Microchip PIC32 has internal parallel flash (non-CFI compliant). These flash devices do not support any identifier command so no standard IDs. Added unique IDs to seperate these flash devices from others supported by U-Boot. Signed-off-by: Purna Chandra Mandal --- include/flash.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/include/flash.h b/include/flash.h index c6321a02ef..2a5e13a13d 100644 --- a/include/flash.h +++ b/include/flash.h @@ -400,6 +400,9 @@ extern flash_info_t *flash_get_info(ulong base); #define FLASH_STM800DT 0x00D7 /* STM M29W800DT (1M = 64K x 16, top) */ #define FLASH_STM800DB 0x005B /* STM M29W800DB (1M = 64K x 16, bottom)*/ +#define FLASH_MCHP100T 0x0060 /* MCHP internal (1M = 64K x 16) */ +#define FLASH_MCHP100B 0x0061 /* MCHP internal (1M = 64K x 16) */ + #define FLASH_28F400_T 0x0062 /* MT 28F400B3 ID ( 4M = 256K x 16 ) */ #define FLASH_28F400_B 0x0063 /* MT 28F400B3 ID ( 4M = 256K x 16 ) */ @@ -486,7 +489,7 @@ extern flash_info_t *flash_get_info(ulong base); #define FLASH_MAN_SHARP 0x00500000 #define FLASH_MAN_ATM 0x00600000 #define FLASH_MAN_CFI 0x01000000 - +#define FLASH_MAN_MCHP 0x02000000 /* Microchip Technology */ #define FLASH_TYPEMASK 0x0000FFFF /* extract FLASH type information */ #define FLASH_VENDMASK 0xFFFF0000 /* extract FLASH vendor information */ From 5c990456999c5672b8e626f945b0e8e17162e02f Mon Sep 17 00:00:00 2001 From: Purna Chandra Mandal Date: Fri, 18 Mar 2016 18:36:08 +0530 Subject: [PATCH 130/162] drivers: mtd: add Microchip PIC32 internal non-CFI flash driver. PIC32 internal flash devices are parallel NOR flash divided into number of banks to allow erase-programming in one while fetch and execution continues on other. As the flash banks are memory mapped stored code can be executed directly from flash (XIP), also there is additional hardware logic to prefetch and cache contents to improve execution performance. These flash can also be used to store user data (like environment). Flash erase and programming are handled by on-chip NVM controller. Driver implemented driver model but MTD is not really support. Signed-off-by: Purna Chandra Mandal Reviewed-by: Simon Glass --- drivers/mtd/Kconfig | 7 + drivers/mtd/Makefile | 1 + drivers/mtd/pic32_flash.c | 444 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 452 insertions(+) create mode 100644 drivers/mtd/pic32_flash.c diff --git a/drivers/mtd/Kconfig b/drivers/mtd/Kconfig index c58841e7d8..390e9e4ea3 100644 --- a/drivers/mtd/Kconfig +++ b/drivers/mtd/Kconfig @@ -28,6 +28,13 @@ config ALTERA_QSPI NOR flash to parallel flash interface. Please find details on the "Embedded Peripherals IP User Guide" of Altera. +config FLASH_PIC32 + bool "Microchip PIC32 Flash driver" + depends on MACH_PIC32 && MTD + help + This enables access to Microchip PIC32 internal non-CFI flash + chips through PIC32 Non-Volatile-Memory Controller. + endmenu source "drivers/mtd/nand/Kconfig" diff --git a/drivers/mtd/Makefile b/drivers/mtd/Makefile index 703700aae0..bd680a784f 100644 --- a/drivers/mtd/Makefile +++ b/drivers/mtd/Makefile @@ -19,5 +19,6 @@ obj-$(CONFIG_HAS_DATAFLASH) += dataflash.o obj-$(CONFIG_FTSMC020) += ftsmc020.o obj-$(CONFIG_FLASH_CFI_LEGACY) += jedec_flash.o obj-$(CONFIG_MW_EEPROM) += mw_eeprom.o +obj-$(CONFIG_FLASH_PIC32) += pic32_flash.o obj-$(CONFIG_ST_SMI) += st_smi.o obj-$(CONFIG_STM32_FLASH) += stm32_flash.o diff --git a/drivers/mtd/pic32_flash.c b/drivers/mtd/pic32_flash.c new file mode 100644 index 0000000000..9166fcd980 --- /dev/null +++ b/drivers/mtd/pic32_flash.c @@ -0,0 +1,444 @@ +/* + * Copyright (C) 2015 + * Cristian Birsan + * Purna Chandra Mandal + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include +#include +#include + +DECLARE_GLOBAL_DATA_PTR; + +/* NVM Controller registers */ +struct pic32_reg_nvm { + struct pic32_reg_atomic ctrl; + struct pic32_reg_atomic key; + struct pic32_reg_atomic addr; + struct pic32_reg_atomic data; +}; + +/* NVM operations */ +#define NVMOP_NOP 0 +#define NVMOP_WORD_WRITE 1 +#define NVMOP_PAGE_ERASE 4 + +/* NVM control bits */ +#define NVM_WR BIT(15) +#define NVM_WREN BIT(14) +#define NVM_WRERR BIT(13) +#define NVM_LVDERR BIT(12) + +/* NVM programming unlock register */ +#define LOCK_KEY 0x0 +#define UNLOCK_KEY1 0xaa996655 +#define UNLOCK_KEY2 0x556699aa + +/* + * PIC32 flash banks consist of number of pages, each page + * into number of rows and rows into number of words. + * Here we will maintain page information instead of sector. + */ +flash_info_t flash_info[CONFIG_SYS_MAX_FLASH_BANKS]; +static struct pic32_reg_nvm *nvm_regs_p; + +static inline void flash_initiate_operation(u32 nvmop) +{ + /* set operation */ + writel(nvmop, &nvm_regs_p->ctrl.raw); + + /* enable flash write */ + writel(NVM_WREN, &nvm_regs_p->ctrl.set); + + /* unlock sequence */ + writel(LOCK_KEY, &nvm_regs_p->key.raw); + writel(UNLOCK_KEY1, &nvm_regs_p->key.raw); + writel(UNLOCK_KEY2, &nvm_regs_p->key.raw); + + /* initiate operation */ + writel(NVM_WR, &nvm_regs_p->ctrl.set); +} + +static int flash_wait_till_busy(const char *func, ulong timeout) +{ + int ret = wait_for_bit(__func__, &nvm_regs_p->ctrl.raw, + NVM_WR, false, timeout, false); + + return ret ? ERR_TIMOUT : ERR_OK; +} + +static inline int flash_complete_operation(void) +{ + u32 tmp; + + tmp = readl(&nvm_regs_p->ctrl.raw); + if (tmp & NVM_WRERR) { + printf("Error in Block Erase - Lock Bit may be set!\n"); + flash_initiate_operation(NVMOP_NOP); + return ERR_PROTECTED; + } + + if (tmp & NVM_LVDERR) { + printf("Error in Block Erase - low-vol detected!\n"); + flash_initiate_operation(NVMOP_NOP); + return ERR_NOT_ERASED; + } + + /* disable flash write or erase operation */ + writel(NVM_WREN, &nvm_regs_p->ctrl.clr); + + return ERR_OK; +} + +/* + * Erase flash sectors, returns: + * ERR_OK - OK + * ERR_INVAL - invalid sector arguments + * ERR_TIMOUT - write timeout + * ERR_NOT_ERASED - Flash not erased + * ERR_UNKNOWN_FLASH_VENDOR - incorrect flash + */ +int flash_erase(flash_info_t *info, int s_first, int s_last) +{ + ulong sect_start, sect_end, flags; + int prot, sect; + int rc; + + if ((info->flash_id & FLASH_VENDMASK) != FLASH_MAN_MCHP) { + printf("Can't erase unknown flash type %08lx - aborted\n", + info->flash_id); + return ERR_UNKNOWN_FLASH_VENDOR; + } + + if ((s_first < 0) || (s_first > s_last)) { + printf("- no sectors to erase\n"); + return ERR_INVAL; + } + + prot = 0; + for (sect = s_first; sect <= s_last; ++sect) { + if (info->protect[sect]) + prot++; + } + + if (prot) + printf("- Warning: %d protected sectors will not be erased!\n", + prot); + else + printf("\n"); + + /* erase on unprotected sectors */ + for (sect = s_first; sect <= s_last; sect++) { + if (info->protect[sect]) + continue; + + /* disable interrupts */ + flags = disable_interrupts(); + + /* write destination page address (physical) */ + sect_start = CPHYSADDR(info->start[sect]); + writel(sect_start, &nvm_regs_p->addr.raw); + + /* page erase */ + flash_initiate_operation(NVMOP_PAGE_ERASE); + + /* wait */ + rc = flash_wait_till_busy(__func__, + CONFIG_SYS_FLASH_ERASE_TOUT); + + /* re-enable interrupts if necessary */ + if (flags) + enable_interrupts(); + + if (rc != ERR_OK) + return rc; + + rc = flash_complete_operation(); + if (rc != ERR_OK) + return rc; + + /* + * flash content is updated but cache might contain stale + * data, so invalidate dcache. + */ + sect_end = info->start[sect] + info->size / info->sector_count; + invalidate_dcache_range(info->start[sect], sect_end); + } + + printf(" done\n"); + return ERR_OK; +} + +int page_erase(flash_info_t *info, int sect) +{ + return 0; +} + +/* Write a word to flash */ +static int write_word(flash_info_t *info, ulong dest, ulong word) +{ + ulong flags; + int rc; + + /* read flash to check if it is sufficiently erased */ + if ((readl((void __iomem *)dest) & word) != word) { + printf("Error, Flash not erased!\n"); + return ERR_NOT_ERASED; + } + + /* disable interrupts */ + flags = disable_interrupts(); + + /* update destination page address (physical) */ + writel(CPHYSADDR(dest), &nvm_regs_p->addr.raw); + writel(word, &nvm_regs_p->data.raw); + + /* word write */ + flash_initiate_operation(NVMOP_WORD_WRITE); + + /* wait for operation to complete */ + rc = flash_wait_till_busy(__func__, CONFIG_SYS_FLASH_WRITE_TOUT); + + /* re-enable interrupts if necessary */ + if (flags) + enable_interrupts(); + + if (rc != ERR_OK) + return rc; + + return flash_complete_operation(); +} + +/* + * Copy memory to flash, returns: + * ERR_OK - OK + * ERR_TIMOUT - write timeout + * ERR_NOT_ERASED - Flash not erased + */ +int write_buff(flash_info_t *info, uchar *src, ulong addr, ulong cnt) +{ + ulong dst, tmp_le, len = cnt; + int i, l, rc; + uchar *cp; + + /* get lower word aligned address */ + dst = (addr & ~3); + + /* handle unaligned start bytes */ + l = addr - dst; + if (l != 0) { + tmp_le = 0; + for (i = 0, cp = (uchar *)dst; i < l; ++i, ++cp) + tmp_le |= *cp << (i * 8); + + for (; (i < 4) && (cnt > 0); ++i, ++src, --cnt, ++cp) + tmp_le |= *src << (i * 8); + + for (; (cnt == 0) && (i < 4); ++i, ++cp) + tmp_le |= *cp << (i * 8); + + rc = write_word(info, dst, tmp_le); + if (rc) + goto out; + + dst += 4; + } + + /* handle word aligned part */ + while (cnt >= 4) { + tmp_le = src[0] | src[1] << 8 | src[2] << 16 | src[3] << 24; + rc = write_word(info, dst, tmp_le); + if (rc) + goto out; + src += 4; + dst += 4; + cnt -= 4; + } + + if (cnt == 0) { + rc = ERR_OK; + goto out; + } + + /* handle unaligned tail bytes */ + tmp_le = 0; + for (i = 0, cp = (uchar *)dst; (i < 4) && (cnt > 0); ++i, ++cp) { + tmp_le |= *src++ << (i * 8); + --cnt; + } + + for (; i < 4; ++i, ++cp) + tmp_le |= *cp << (i * 8); + + rc = write_word(info, dst, tmp_le); +out: + /* + * flash content updated by nvm controller but CPU cache might + * have stale data, so invalidate dcache. + */ + invalidate_dcache_range(addr, addr + len); + + printf(" done\n"); + return rc; +} + +void flash_print_info(flash_info_t *info) +{ + int i; + + if (info->flash_id == FLASH_UNKNOWN) { + printf("missing or unknown FLASH type\n"); + return; + } + + switch (info->flash_id & FLASH_VENDMASK) { + case FLASH_MAN_MCHP: + printf("Microchip Technology "); + break; + default: + printf("Unknown Vendor "); + break; + } + + switch (info->flash_id & FLASH_TYPEMASK) { + case FLASH_MCHP100T: + printf("Internal (8 Mbit, 64 x 16k)\n"); + break; + default: + printf("Unknown Chip Type\n"); + break; + } + + printf(" Size: %ld MB in %d Sectors\n", + info->size >> 20, info->sector_count); + + printf(" Sector Start Addresses:"); + for (i = 0; i < info->sector_count; ++i) { + if ((i % 5) == 0) + printf("\n "); + + printf(" %08lX%s", info->start[i], + info->protect[i] ? " (RO)" : " "); + } + printf("\n"); +} + +unsigned long flash_init(void) +{ + unsigned long size = 0; + struct udevice *dev; + int bank; + + /* probe every MTD device */ + for (uclass_first_device(UCLASS_MTD, &dev); dev; + uclass_next_device(&dev)) { + /* nop */ + } + + /* calc total flash size */ + for (bank = 0; bank < CONFIG_SYS_MAX_FLASH_BANKS; ++bank) + size += flash_info[bank].size; + + return size; +} + +static void pic32_flash_bank_init(flash_info_t *info, + ulong base, ulong size) +{ + ulong sect_size; + int sect; + + /* device & manufacturer code */ + info->flash_id = FLASH_MAN_MCHP | FLASH_MCHP100T; + info->sector_count = CONFIG_SYS_MAX_FLASH_SECT; + info->size = size; + + /* update sector (i.e page) info */ + sect_size = info->size / info->sector_count; + for (sect = 0; sect < info->sector_count; sect++) { + info->start[sect] = base; + /* protect each sector by default */ + info->protect[sect] = 1; + base += sect_size; + } +} + +static int pic32_flash_probe(struct udevice *dev) +{ + void *blob = (void *)gd->fdt_blob; + int node = dev->of_offset; + const char *list, *end; + const fdt32_t *cell; + unsigned long addr, size; + int parent, addrc, sizec; + flash_info_t *info; + int len, idx; + + /* + * decode regs. there are multiple reg tuples, and they need to + * match with reg-names. + */ + parent = fdt_parent_offset(blob, node); + of_bus_default_count_cells(blob, parent, &addrc, &sizec); + list = fdt_getprop(blob, node, "reg-names", &len); + if (!list) + return -ENOENT; + + end = list + len; + cell = fdt_getprop(blob, node, "reg", &len); + if (!cell) + return -ENOENT; + + for (idx = 0, info = &flash_info[0]; list < end;) { + addr = fdt_translate_address((void *)blob, node, cell + idx); + size = fdt_addr_to_cpu(cell[idx + addrc]); + len = strlen(list); + if (!strncmp(list, "nvm", len)) { + /* NVM controller */ + nvm_regs_p = ioremap(addr, size); + } else if (!strncmp(list, "bank", 4)) { + /* Flash bank: use kseg0 cached address */ + pic32_flash_bank_init(info, CKSEG0ADDR(addr), size); + info++; + } + idx += addrc + sizec; + list += len + 1; + } + + /* disable flash write/erase operations */ + writel(NVM_WREN, &nvm_regs_p->ctrl.clr); + +#if (CONFIG_SYS_MONITOR_BASE >= CONFIG_SYS_FLASH_BASE) + /* monitor protection ON by default */ + flash_protect(FLAG_PROTECT_SET, + CONFIG_SYS_MONITOR_BASE, + CONFIG_SYS_MONITOR_BASE + monitor_flash_len - 1, + &flash_info[0]); +#endif + +#ifdef CONFIG_ENV_IS_IN_FLASH + /* ENV protection ON by default */ + flash_protect(FLAG_PROTECT_SET, + CONFIG_ENV_ADDR, + CONFIG_ENV_ADDR + CONFIG_ENV_SECT_SIZE - 1, + &flash_info[0]); +#endif + return 0; +} + +static const struct udevice_id pic32_flash_ids[] = { + { .compatible = "microchip,pic32mzda-flash" }, + {} +}; + +U_BOOT_DRIVER(pic32_flash) = { + .name = "pic32_flash", + .id = UCLASS_MTD, + .of_match = pic32_flash_ids, + .probe = pic32_flash_probe, +}; From 8cf7a418bcff0492285d7dd2687bd42aaa377e5d Mon Sep 17 00:00:00 2001 From: Tim Chick Date: Thu, 31 Mar 2016 12:51:20 +0100 Subject: [PATCH 131/162] mips: Report reloc information in bdinfo Signed-off-by: Tim Chick --- cmd/bdinfo.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/cmd/bdinfo.c b/cmd/bdinfo.c index 8eda68b4f9..1c4bed96b5 100644 --- a/cmd/bdinfo.c +++ b/cmd/bdinfo.c @@ -341,6 +341,8 @@ int do_bdinfo(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) print_eth(0); printf("ip_addr = %s\n", getenv("ipaddr")); printf("baudrate = %u bps\n", gd->baudrate); + print_num("relocaddr", gd->relocaddr); + print_num("reloc off", gd->reloc_off); return 0; } From 5fabf2e7da1b738c6e0353b6a5a17b1a77ecc2e9 Mon Sep 17 00:00:00 2001 From: Wills Wang Date: Tue, 12 Apr 2016 11:09:18 +0800 Subject: [PATCH 132/162] ath79: spi: Remove the explicit pinctrl setting The correct pinctrl is handled automatically so we don't need to do it in the driver. Signed-off-by: Wills Wang --- drivers/spi/ath79_spi.c | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/drivers/spi/ath79_spi.c b/drivers/spi/ath79_spi.c index 0c1022da05..b18c733b67 100644 --- a/drivers/spi/ath79_spi.c +++ b/drivers/spi/ath79_spi.c @@ -175,19 +175,7 @@ static int ath79_spi_set_mode(struct udevice *bus, uint mode) static int ath79_spi_probe(struct udevice *bus) { struct ath79_spi_priv *priv = dev_get_priv(bus); - struct udevice *pinctrl; fdt_addr_t addr; - int ret; - - ret = uclass_get_device(UCLASS_PINCTRL, 0, &pinctrl); - if (ret) - return ret; - ret = pinctrl_get_periph_id(pinctrl, bus); - if (ret < 0) - return ret; - ret = pinctrl_request(pinctrl, ret, 0); - if (ret < 0) - return ret; addr = dev_get_addr(bus); if (addr == FDT_ADDR_T_NONE) From 773f3b25384363d53e457f1faae77c91db76e0c4 Mon Sep 17 00:00:00 2001 From: Wills Wang Date: Tue, 12 Apr 2016 11:09:19 +0800 Subject: [PATCH 133/162] ar933x: serial: Remove the explicit pinctrl setting The correct pinctrl is handled automatically so we don't need to do it in the driver. Signed-off-by: Wills Wang --- drivers/serial/serial_ar933x.c | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) diff --git a/drivers/serial/serial_ar933x.c b/drivers/serial/serial_ar933x.c index d43f9c97d7..aae66dc682 100644 --- a/drivers/serial/serial_ar933x.c +++ b/drivers/serial/serial_ar933x.c @@ -38,6 +38,7 @@ struct ar933x_serial_priv { }; /* + * Baudrate algorithm come from Linux/drivers/tty/serial/ar933x_uart.c * baudrate = (clk / (scale + 1)) * (step * (1 / 2^17)) */ static u32 ar933x_serial_get_baud(u32 clk, u32 scale, u32 step) @@ -145,27 +146,14 @@ static int ar933x_serial_pending(struct udevice *dev, bool input) static int ar933x_serial_probe(struct udevice *dev) { struct ar933x_serial_priv *priv = dev_get_priv(dev); - struct udevice *pinctrl; fdt_addr_t addr; u32 val; - int ret; - - ret = uclass_get_device(UCLASS_PINCTRL, 0, &pinctrl); - if (ret) - return ret; - ret = pinctrl_get_periph_id(pinctrl, dev); - if (ret < 0) - return ret; - ret = pinctrl_request(pinctrl, ret, 0); - if (ret < 0) - return ret; addr = dev_get_addr(dev); if (addr == FDT_ADDR_T_NONE) return -EINVAL; - priv->regs = map_physmem(addr, - AR933X_UART_SIZE, + priv->regs = map_physmem(addr, AR933X_UART_SIZE, MAP_NOCACHE); /* From 5691d10a0166d5a324f96d98757f206c6dedc989 Mon Sep 17 00:00:00 2001 From: Wills Wang Date: Tue, 12 Apr 2016 11:09:20 +0800 Subject: [PATCH 134/162] ath79: ar933x: use BIT macro for bit shift operation used a uniform BIT macro for register bit-field shift Signed-off-by: Wills Wang --- arch/mips/mach-ath79/ar933x/ddr.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/arch/mips/mach-ath79/ar933x/ddr.c b/arch/mips/mach-ath79/ar933x/ddr.c index 74e8e80ea7..91452bcc53 100644 --- a/arch/mips/mach-ath79/ar933x/ddr.c +++ b/arch/mips/mach-ath79/ar933x/ddr.c @@ -21,7 +21,7 @@ DECLARE_GLOBAL_DATA_PTR; #define DDR_CTRL_UPD_EMRS BIT(1) #define DDR_CTRL_UPD_MRS BIT(0) -#define DDR_REFRESH_EN (1 << 14) +#define DDR_REFRESH_EN BIT(14) #define DDR_REFRESH_M 0x3ff #define DDR_REFRESH(x) ((x) & 0x3ff) #define DDR_REFRESH_VAL_25M (DDR_REFRESH_EN | DDR_REFRESH(390)) @@ -48,7 +48,7 @@ DECLARE_GLOBAL_DATA_PTR; #define DDR_CAS_L_M 0x17 #define DDR_CAS_L_S 27 #define DDR_CAS_L(x) (((x) & DDR_CAS_L_M) << DDR_CAS_L_S) -#define DDR_OPEN (1 << 30) +#define DDR_OPEN BIT(30) #define DDR_CONF_REG_VAL (DDR_TRAS(16) | DDR_TRCD(6) | \ DDR_TRP(6) | DDR_TRRD(4) | \ DDR_TRFC(30) | DDR_TMRD(15) | \ @@ -57,10 +57,10 @@ DECLARE_GLOBAL_DATA_PTR; #define DDR_BURST_LEN_S 0 #define DDR_BURST_LEN_M 0xf #define DDR_BURST_LEN(x) ((x) << DDR_BURST_LEN_S) -#define DDR_BURST_TYPE (1 << 4) -#define DDR_CNTL_OE_EN (1 << 5) -#define DDR_PHASE_SEL (1 << 6) -#define DDR_CKE (1 << 7) +#define DDR_BURST_TYPE BIT(4) +#define DDR_CNTL_OE_EN BIT(5) +#define DDR_PHASE_SEL BIT(6) +#define DDR_CKE BIT(7) #define DDR_TWR_S 8 #define DDR_TWR_M 0xf #define DDR_TWR(x) ((x) << DDR_TWR_S) @@ -76,7 +76,7 @@ DECLARE_GLOBAL_DATA_PTR; #define DDR_G_OPEN_L_S 26 #define DDR_G_OPEN_L_M 0xf #define DDR_G_OPEN_L(x) ((x) << DDR_G_OPEN_L_S) -#define DDR_HALF_WIDTH_LOW (1 << 31) +#define DDR_HALF_WIDTH_LOW BIT(31) #define DDR_CONF2_REG_VAL (DDR_BURST_LEN(8) | DDR_CNTL_OE_EN | \ DDR_CKE | DDR_TWR(6) | DDR_TRTW(14) | \ DDR_TRTP(8) | DDR_TWTR(14) | \ From 59e4080c7e4d85bd29c343ea9167794feceadc3e Mon Sep 17 00:00:00 2001 From: Wills Wang Date: Tue, 12 Apr 2016 18:24:10 +0800 Subject: [PATCH 135/162] ath79: add readonly attribute for ath79_soc_desc use 'const' keywork to qualify readonly attribute for lookup-table member Signed-off-by: Wills Wang --- arch/mips/mach-ath79/cpu.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/mips/mach-ath79/cpu.c b/arch/mips/mach-ath79/cpu.c index c6122f2bcc..5756a06d50 100644 --- a/arch/mips/mach-ath79/cpu.c +++ b/arch/mips/mach-ath79/cpu.c @@ -12,13 +12,13 @@ #include struct ath79_soc_desc { - enum ath79_soc_type soc; + const enum ath79_soc_type soc; const char *chip; - int major; - int minor; + const int major; + const int minor; }; -static struct ath79_soc_desc desc[] = { +static const struct ath79_soc_desc desc[] = { {ATH79_SOC_AR7130, "7130", REV_ID_MAJOR_AR71XX, AR71XX_REV_ID_MINOR_AR7130}, {ATH79_SOC_AR7141, "7141", From 5760fc7850a9ad98a8852200ea879bfccd66df26 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Thu, 5 May 2016 20:14:00 +0200 Subject: [PATCH 136/162] mips: Fix compiler warning in cpu.c There really is zero reason for including netdev.h in generic mips CPU code. Removing the netdev.h from cpu.c also fixes the following compiler warning: In file included from arch/mips/cpu/cpu.c:10:0: include/netdev.h:204:41: warning: 'struct eth_device' declared inside parameter list [enabled by default] int fecmxc_register_mii_postcall(struct eth_device *dev, int (*cb)(int)); ^ include/netdev.h:204:41: warning: its scope is only this definition or declaration, which is probably not what you want [enabled by default] Signed-off-by: Marek Vasut Cc: Paul Burton Cc: Daniel Schwierzeck --- arch/mips/cpu/cpu.c | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/mips/cpu/cpu.c b/arch/mips/cpu/cpu.c index 8d3b2f5c2b..391feb3250 100644 --- a/arch/mips/cpu/cpu.c +++ b/arch/mips/cpu/cpu.c @@ -7,7 +7,6 @@ #include #include -#include #include #include #include From 0a0a958b68ee9d78a7cbccb5f72b95e1d488c9bd Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Fri, 6 May 2016 20:10:33 +0200 Subject: [PATCH 137/162] mips: Add MIPS 74Kc tune Add MIPS 74Kc tune Kconfig option. Signed-off-by: Marek Vasut Cc: Daniel Schwierzeck Cc: Wills Wang [added missing tune-y entry in arch/mips/Makefile] Signed-off-by: Daniel Schwierzeck --- arch/mips/Kconfig | 3 +++ arch/mips/Makefile | 1 + 2 files changed, 4 insertions(+) diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 7162f3c1ec..188aaba92f 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -198,6 +198,9 @@ config MIPS_TUNE_14KC config MIPS_TUNE_24KC bool +config MIPS_TUNE_74KC + bool + config 32BIT bool diff --git a/arch/mips/Makefile b/arch/mips/Makefile index 7a82316130..94f7e16e41 100644 --- a/arch/mips/Makefile +++ b/arch/mips/Makefile @@ -26,6 +26,7 @@ arch-$(CONFIG_CPU_MIPS64_R2) += -march=mips64r2 -Wa,-mips64r2 tune-$(CONFIG_MIPS_TUNE_4KC) += -mtune=4kc tune-$(CONFIG_MIPS_TUNE_14KC) += -mtune=14kc tune-$(CONFIG_MIPS_TUNE_24KC) += -mtune=24kc +tune-$(CONFIG_MIPS_TUNE_74KC) += -mtune=74kc # Include default header files cflags-y += -I$(srctree)/arch/mips/include/asm/mach-generic From 0a6767efabedbddc2351d14695aa3a7d63657e2c Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Fri, 6 May 2016 20:10:34 +0200 Subject: [PATCH 138/162] mips: ath79: Fix ar71xx_regs.h indent The indent in this file triggers my OCD, so fix it. Replace multiple spaces with tabs and align the values in one column. Signed-off-by: Marek Vasut Cc: Daniel Schwierzeck Cc: Wills Wang --- .../mach-ath79/include/mach/ar71xx_regs.h | 1903 +++++++++-------- 1 file changed, 969 insertions(+), 934 deletions(-) diff --git a/arch/mips/mach-ath79/include/mach/ar71xx_regs.h b/arch/mips/mach-ath79/include/mach/ar71xx_regs.h index 893dedc2a4..bff9d0594d 100644 --- a/arch/mips/mach-ath79/include/mach/ar71xx_regs.h +++ b/arch/mips/mach-ath79/include/mach/ar71xx_regs.h @@ -16,709 +16,744 @@ #include #else #ifndef BIT -#define BIT(nr) (1 << (nr)) +#define BIT(nr) (1 << (nr)) #endif #endif -#define AR71XX_APB_BASE 0x18000000 -#define AR71XX_GE0_BASE 0x19000000 -#define AR71XX_GE0_SIZE 0x10000 -#define AR71XX_GE1_BASE 0x1a000000 -#define AR71XX_GE1_SIZE 0x10000 -#define AR71XX_EHCI_BASE 0x1b000000 -#define AR71XX_EHCI_SIZE 0x1000 -#define AR71XX_OHCI_BASE 0x1c000000 -#define AR71XX_OHCI_SIZE 0x1000 -#define AR71XX_SPI_BASE 0x1f000000 -#define AR71XX_SPI_SIZE 0x01000000 +#define AR71XX_APB_BASE 0x18000000 +#define AR71XX_GE0_BASE 0x19000000 +#define AR71XX_GE0_SIZE 0x10000 +#define AR71XX_GE1_BASE 0x1a000000 +#define AR71XX_GE1_SIZE 0x10000 +#define AR71XX_EHCI_BASE 0x1b000000 +#define AR71XX_EHCI_SIZE 0x1000 +#define AR71XX_OHCI_BASE 0x1c000000 +#define AR71XX_OHCI_SIZE 0x1000 +#define AR71XX_SPI_BASE 0x1f000000 +#define AR71XX_SPI_SIZE 0x01000000 -#define AR71XX_DDR_CTRL_BASE (AR71XX_APB_BASE + 0x00000000) -#define AR71XX_DDR_CTRL_SIZE 0x100 -#define AR71XX_UART_BASE (AR71XX_APB_BASE + 0x00020000) -#define AR71XX_UART_SIZE 0x100 -#define AR71XX_USB_CTRL_BASE (AR71XX_APB_BASE + 0x00030000) -#define AR71XX_USB_CTRL_SIZE 0x100 -#define AR71XX_GPIO_BASE (AR71XX_APB_BASE + 0x00040000) -#define AR71XX_GPIO_SIZE 0x100 -#define AR71XX_PLL_BASE (AR71XX_APB_BASE + 0x00050000) -#define AR71XX_PLL_SIZE 0x100 -#define AR71XX_RESET_BASE (AR71XX_APB_BASE + 0x00060000) -#define AR71XX_RESET_SIZE 0x100 -#define AR71XX_MII_BASE (AR71XX_APB_BASE + 0x00070000) -#define AR71XX_MII_SIZE 0x100 +#define AR71XX_DDR_CTRL_BASE \ + (AR71XX_APB_BASE + 0x00000000) +#define AR71XX_DDR_CTRL_SIZE 0x100 +#define AR71XX_UART_BASE \ + (AR71XX_APB_BASE + 0x00020000) +#define AR71XX_UART_SIZE 0x100 +#define AR71XX_USB_CTRL_BASE \ + (AR71XX_APB_BASE + 0x00030000) +#define AR71XX_USB_CTRL_SIZE 0x100 +#define AR71XX_GPIO_BASE \ + (AR71XX_APB_BASE + 0x00040000) +#define AR71XX_GPIO_SIZE 0x100 +#define AR71XX_PLL_BASE \ + (AR71XX_APB_BASE + 0x00050000) +#define AR71XX_PLL_SIZE 0x100 +#define AR71XX_RESET_BASE \ + (AR71XX_APB_BASE + 0x00060000) +#define AR71XX_RESET_SIZE 0x100 +#define AR71XX_MII_BASE \ + (AR71XX_APB_BASE + 0x00070000) +#define AR71XX_MII_SIZE 0x100 -#define AR71XX_PCI_MEM_BASE 0x10000000 -#define AR71XX_PCI_MEM_SIZE 0x07000000 +#define AR71XX_PCI_MEM_BASE 0x10000000 +#define AR71XX_PCI_MEM_SIZE 0x07000000 -#define AR71XX_PCI_WIN0_OFFS 0x10000000 -#define AR71XX_PCI_WIN1_OFFS 0x11000000 -#define AR71XX_PCI_WIN2_OFFS 0x12000000 -#define AR71XX_PCI_WIN3_OFFS 0x13000000 -#define AR71XX_PCI_WIN4_OFFS 0x14000000 -#define AR71XX_PCI_WIN5_OFFS 0x15000000 -#define AR71XX_PCI_WIN6_OFFS 0x16000000 -#define AR71XX_PCI_WIN7_OFFS 0x07000000 +#define AR71XX_PCI_WIN0_OFFS 0x10000000 +#define AR71XX_PCI_WIN1_OFFS 0x11000000 +#define AR71XX_PCI_WIN2_OFFS 0x12000000 +#define AR71XX_PCI_WIN3_OFFS 0x13000000 +#define AR71XX_PCI_WIN4_OFFS 0x14000000 +#define AR71XX_PCI_WIN5_OFFS 0x15000000 +#define AR71XX_PCI_WIN6_OFFS 0x16000000 +#define AR71XX_PCI_WIN7_OFFS 0x07000000 #define AR71XX_PCI_CFG_BASE \ (AR71XX_PCI_MEM_BASE + AR71XX_PCI_WIN7_OFFS + 0x10000) -#define AR71XX_PCI_CFG_SIZE 0x100 +#define AR71XX_PCI_CFG_SIZE 0x100 -#define AR7240_USB_CTRL_BASE (AR71XX_APB_BASE + 0x00030000) -#define AR7240_USB_CTRL_SIZE 0x100 -#define AR7240_OHCI_BASE 0x1b000000 -#define AR7240_OHCI_SIZE 0x1000 +#define AR7240_USB_CTRL_BASE \ + (AR71XX_APB_BASE + 0x00030000) +#define AR7240_USB_CTRL_SIZE 0x100 +#define AR7240_OHCI_BASE 0x1b000000 +#define AR7240_OHCI_SIZE 0x1000 -#define AR724X_PCI_MEM_BASE 0x10000000 -#define AR724X_PCI_MEM_SIZE 0x04000000 +#define AR724X_PCI_MEM_BASE 0x10000000 +#define AR724X_PCI_MEM_SIZE 0x04000000 -#define AR724X_PCI_CFG_BASE 0x14000000 -#define AR724X_PCI_CFG_SIZE 0x1000 -#define AR724X_PCI_CRP_BASE (AR71XX_APB_BASE + 0x000c0000) -#define AR724X_PCI_CRP_SIZE 0x1000 -#define AR724X_PCI_CTRL_BASE (AR71XX_APB_BASE + 0x000f0000) -#define AR724X_PCI_CTRL_SIZE 0x100 +#define AR724X_PCI_CFG_BASE 0x14000000 +#define AR724X_PCI_CFG_SIZE 0x1000 +#define AR724X_PCI_CRP_BASE \ + (AR71XX_APB_BASE + 0x000c0000) +#define AR724X_PCI_CRP_SIZE 0x1000 +#define AR724X_PCI_CTRL_BASE \ + (AR71XX_APB_BASE + 0x000f0000) +#define AR724X_PCI_CTRL_SIZE 0x100 -#define AR724X_EHCI_BASE 0x1b000000 -#define AR724X_EHCI_SIZE 0x1000 +#define AR724X_EHCI_BASE 0x1b000000 +#define AR724X_EHCI_SIZE 0x1000 -#define AR913X_EHCI_BASE 0x1b000000 -#define AR913X_EHCI_SIZE 0x1000 -#define AR913X_WMAC_BASE (AR71XX_APB_BASE + 0x000C0000) -#define AR913X_WMAC_SIZE 0x30000 +#define AR913X_EHCI_BASE 0x1b000000 +#define AR913X_EHCI_SIZE 0x1000 +#define AR913X_WMAC_BASE \ + (AR71XX_APB_BASE + 0x000C0000) +#define AR913X_WMAC_SIZE 0x30000 -#define AR933X_UART_BASE (AR71XX_APB_BASE + 0x00020000) -#define AR933X_UART_SIZE 0x14 -#define AR933X_GMAC_BASE (AR71XX_APB_BASE + 0x00070000) -#define AR933X_GMAC_SIZE 0x04 -#define AR933X_WMAC_BASE (AR71XX_APB_BASE + 0x00100000) -#define AR933X_WMAC_SIZE 0x20000 -#define AR933X_RTC_BASE (AR71XX_APB_BASE + 0x00107000) -#define AR933X_RTC_SIZE 0x1000 -#define AR933X_EHCI_BASE 0x1b000000 -#define AR933X_EHCI_SIZE 0x1000 -#define AR933X_SRIF_BASE (AR71XX_APB_BASE + 0x00116000) -#define AR933X_SRIF_SIZE 0x1000 +#define AR933X_UART_BASE \ + (AR71XX_APB_BASE + 0x00020000) +#define AR933X_UART_SIZE 0x14 +#define AR933X_GMAC_BASE \ + (AR71XX_APB_BASE + 0x00070000) +#define AR933X_GMAC_SIZE 0x04 +#define AR933X_WMAC_BASE \ + (AR71XX_APB_BASE + 0x00100000) +#define AR933X_WMAC_SIZE 0x20000 +#define AR933X_RTC_BASE \ + (AR71XX_APB_BASE + 0x00107000) +#define AR933X_RTC_SIZE 0x1000 +#define AR933X_EHCI_BASE 0x1b000000 +#define AR933X_EHCI_SIZE 0x1000 +#define AR933X_SRIF_BASE \ + (AR71XX_APB_BASE + 0x00116000) +#define AR933X_SRIF_SIZE 0x1000 -#define AR934X_GMAC_BASE (AR71XX_APB_BASE + 0x00070000) -#define AR934X_GMAC_SIZE 0x14 -#define AR934X_WMAC_BASE (AR71XX_APB_BASE + 0x00100000) -#define AR934X_WMAC_SIZE 0x20000 -#define AR934X_EHCI_BASE 0x1b000000 -#define AR934X_EHCI_SIZE 0x200 -#define AR934X_NFC_BASE 0x1b000200 -#define AR934X_NFC_SIZE 0xb8 -#define AR934X_SRIF_BASE (AR71XX_APB_BASE + 0x00116000) -#define AR934X_SRIF_SIZE 0x1000 +#define AR934X_GMAC_BASE \ + (AR71XX_APB_BASE + 0x00070000) +#define AR934X_GMAC_SIZE 0x14 +#define AR934X_WMAC_BASE \ + (AR71XX_APB_BASE + 0x00100000) +#define AR934X_WMAC_SIZE 0x20000 +#define AR934X_EHCI_BASE 0x1b000000 +#define AR934X_EHCI_SIZE 0x200 +#define AR934X_NFC_BASE 0x1b000200 +#define AR934X_NFC_SIZE 0xb8 +#define AR934X_SRIF_BASE \ + (AR71XX_APB_BASE + 0x00116000) +#define AR934X_SRIF_SIZE 0x1000 -#define QCA953X_GMAC_BASE (AR71XX_APB_BASE + 0x00070000) -#define QCA953X_GMAC_SIZE 0x14 -#define QCA953X_WMAC_BASE (AR71XX_APB_BASE + 0x00100000) -#define QCA953X_WMAC_SIZE 0x20000 -#define QCA953X_RTC_BASE (AR71XX_APB_BASE + 0x00107000) -#define QCA953X_RTC_SIZE 0x1000 -#define QCA953X_EHCI_BASE 0x1b000000 -#define QCA953X_EHCI_SIZE 0x200 -#define QCA953X_SRIF_BASE (AR71XX_APB_BASE + 0x00116000) -#define QCA953X_SRIF_SIZE 0x1000 +#define QCA953X_GMAC_BASE \ + (AR71XX_APB_BASE + 0x00070000) +#define QCA953X_GMAC_SIZE 0x14 +#define QCA953X_WMAC_BASE \ + (AR71XX_APB_BASE + 0x00100000) +#define QCA953X_WMAC_SIZE 0x20000 +#define QCA953X_RTC_BASE \ + (AR71XX_APB_BASE + 0x00107000) +#define QCA953X_RTC_SIZE 0x1000 +#define QCA953X_EHCI_BASE 0x1b000000 +#define QCA953X_EHCI_SIZE 0x200 +#define QCA953X_SRIF_BASE \ + (AR71XX_APB_BASE + 0x00116000) +#define QCA953X_SRIF_SIZE 0x1000 -#define QCA953X_PCI_CFG_BASE0 0x14000000 -#define QCA953X_PCI_CTRL_BASE0 (AR71XX_APB_BASE + 0x000f0000) -#define QCA953X_PCI_CRP_BASE0 (AR71XX_APB_BASE + 0x000c0000) -#define QCA953X_PCI_MEM_BASE0 0x10000000 -#define QCA953X_PCI_MEM_SIZE 0x02000000 +#define QCA953X_PCI_CFG_BASE0 0x14000000 +#define QCA953X_PCI_CTRL_BASE0 \ + (AR71XX_APB_BASE + 0x000f0000) +#define QCA953X_PCI_CRP_BASE0 \ + (AR71XX_APB_BASE + 0x000c0000) +#define QCA953X_PCI_MEM_BASE0 0x10000000 +#define QCA953X_PCI_MEM_SIZE 0x02000000 -#define QCA955X_PCI_MEM_BASE0 0x10000000 -#define QCA955X_PCI_MEM_BASE1 0x12000000 -#define QCA955X_PCI_MEM_SIZE 0x02000000 -#define QCA955X_PCI_CFG_BASE0 0x14000000 -#define QCA955X_PCI_CFG_BASE1 0x16000000 -#define QCA955X_PCI_CFG_SIZE 0x1000 -#define QCA955X_PCI_CRP_BASE0 (AR71XX_APB_BASE + 0x000c0000) -#define QCA955X_PCI_CRP_BASE1 (AR71XX_APB_BASE + 0x00250000) -#define QCA955X_PCI_CRP_SIZE 0x1000 -#define QCA955X_PCI_CTRL_BASE0 (AR71XX_APB_BASE + 0x000f0000) -#define QCA955X_PCI_CTRL_BASE1 (AR71XX_APB_BASE + 0x00280000) -#define QCA955X_PCI_CTRL_SIZE 0x100 +#define QCA955X_PCI_MEM_BASE0 0x10000000 +#define QCA955X_PCI_MEM_BASE1 0x12000000 +#define QCA955X_PCI_MEM_SIZE 0x02000000 +#define QCA955X_PCI_CFG_BASE0 0x14000000 +#define QCA955X_PCI_CFG_BASE1 0x16000000 +#define QCA955X_PCI_CFG_SIZE 0x1000 +#define QCA955X_PCI_CRP_BASE0 \ + (AR71XX_APB_BASE + 0x000c0000) +#define QCA955X_PCI_CRP_BASE1 \ + (AR71XX_APB_BASE + 0x00250000) +#define QCA955X_PCI_CRP_SIZE 0x1000 +#define QCA955X_PCI_CTRL_BASE0 \ + (AR71XX_APB_BASE + 0x000f0000) +#define QCA955X_PCI_CTRL_BASE1 \ + (AR71XX_APB_BASE + 0x00280000) +#define QCA955X_PCI_CTRL_SIZE 0x100 -#define QCA955X_GMAC_BASE (AR71XX_APB_BASE + 0x00070000) -#define QCA955X_GMAC_SIZE 0x40 -#define QCA955X_WMAC_BASE (AR71XX_APB_BASE + 0x00100000) -#define QCA955X_WMAC_SIZE 0x20000 -#define QCA955X_EHCI0_BASE 0x1b000000 -#define QCA955X_EHCI1_BASE 0x1b400000 -#define QCA955X_EHCI_SIZE 0x1000 -#define QCA955X_NFC_BASE 0x1b800200 -#define QCA955X_NFC_SIZE 0xb8 +#define QCA955X_GMAC_BASE \ + (AR71XX_APB_BASE + 0x00070000) +#define QCA955X_GMAC_SIZE 0x40 +#define QCA955X_WMAC_BASE \ + (AR71XX_APB_BASE + 0x00100000) +#define QCA955X_WMAC_SIZE 0x20000 +#define QCA955X_EHCI0_BASE 0x1b000000 +#define QCA955X_EHCI1_BASE 0x1b400000 +#define QCA955X_EHCI_SIZE 0x1000 +#define QCA955X_NFC_BASE 0x1b800200 +#define QCA955X_NFC_SIZE 0xb8 -#define QCA956X_PCI_MEM_BASE1 0x12000000 -#define QCA956X_PCI_MEM_SIZE 0x02000000 -#define QCA956X_PCI_CFG_BASE1 0x16000000 -#define QCA956X_PCI_CFG_SIZE 0x1000 -#define QCA956X_PCI_CRP_BASE1 (AR71XX_APB_BASE + 0x00250000) -#define QCA956X_PCI_CRP_SIZE 0x1000 -#define QCA956X_PCI_CTRL_BASE1 (AR71XX_APB_BASE + 0x00280000) -#define QCA956X_PCI_CTRL_SIZE 0x100 +#define QCA956X_PCI_MEM_BASE1 0x12000000 +#define QCA956X_PCI_MEM_SIZE 0x02000000 +#define QCA956X_PCI_CFG_BASE1 0x16000000 +#define QCA956X_PCI_CFG_SIZE 0x1000 +#define QCA956X_PCI_CRP_BASE1 \ + (AR71XX_APB_BASE + 0x00250000) +#define QCA956X_PCI_CRP_SIZE 0x1000 +#define QCA956X_PCI_CTRL_BASE1 \ + (AR71XX_APB_BASE + 0x00280000) +#define QCA956X_PCI_CTRL_SIZE 0x100 -#define QCA956X_WMAC_BASE (AR71XX_APB_BASE + 0x00100000) -#define QCA956X_WMAC_SIZE 0x20000 -#define QCA956X_EHCI0_BASE 0x1b000000 -#define QCA956X_EHCI1_BASE 0x1b400000 -#define QCA956X_EHCI_SIZE 0x200 -#define QCA956X_GMAC_BASE (AR71XX_APB_BASE + 0x00070000) -#define QCA956X_GMAC_SIZE 0x64 +#define QCA956X_WMAC_BASE \ + (AR71XX_APB_BASE + 0x00100000) +#define QCA956X_WMAC_SIZE 0x20000 +#define QCA956X_EHCI0_BASE 0x1b000000 +#define QCA956X_EHCI1_BASE 0x1b400000 +#define QCA956X_EHCI_SIZE 0x200 +#define QCA956X_GMAC_BASE \ + (AR71XX_APB_BASE + 0x00070000) +#define QCA956X_GMAC_SIZE 0x64 /* * DDR_CTRL block */ -#define AR71XX_DDR_REG_CONFIG 0x00 -#define AR71XX_DDR_REG_CONFIG2 0x04 -#define AR71XX_DDR_REG_MODE 0x08 -#define AR71XX_DDR_REG_EMR 0x0c -#define AR71XX_DDR_REG_CONTROL 0x10 -#define AR71XX_DDR_REG_REFRESH 0x14 -#define AR71XX_DDR_REG_RD_CYCLE 0x18 -#define AR71XX_DDR_REG_TAP_CTRL0 0x1c -#define AR71XX_DDR_REG_TAP_CTRL1 0x20 +#define AR71XX_DDR_REG_CONFIG 0x00 +#define AR71XX_DDR_REG_CONFIG2 0x04 +#define AR71XX_DDR_REG_MODE 0x08 +#define AR71XX_DDR_REG_EMR 0x0c +#define AR71XX_DDR_REG_CONTROL 0x10 +#define AR71XX_DDR_REG_REFRESH 0x14 +#define AR71XX_DDR_REG_RD_CYCLE 0x18 +#define AR71XX_DDR_REG_TAP_CTRL0 0x1c +#define AR71XX_DDR_REG_TAP_CTRL1 0x20 -#define AR71XX_DDR_REG_PCI_WIN0 0x7c -#define AR71XX_DDR_REG_PCI_WIN1 0x80 -#define AR71XX_DDR_REG_PCI_WIN2 0x84 -#define AR71XX_DDR_REG_PCI_WIN3 0x88 -#define AR71XX_DDR_REG_PCI_WIN4 0x8c -#define AR71XX_DDR_REG_PCI_WIN5 0x90 -#define AR71XX_DDR_REG_PCI_WIN6 0x94 -#define AR71XX_DDR_REG_PCI_WIN7 0x98 -#define AR71XX_DDR_REG_FLUSH_GE0 0x9c -#define AR71XX_DDR_REG_FLUSH_GE1 0xa0 -#define AR71XX_DDR_REG_FLUSH_USB 0xa4 -#define AR71XX_DDR_REG_FLUSH_PCI 0xa8 +#define AR71XX_DDR_REG_PCI_WIN0 0x7c +#define AR71XX_DDR_REG_PCI_WIN1 0x80 +#define AR71XX_DDR_REG_PCI_WIN2 0x84 +#define AR71XX_DDR_REG_PCI_WIN3 0x88 +#define AR71XX_DDR_REG_PCI_WIN4 0x8c +#define AR71XX_DDR_REG_PCI_WIN5 0x90 +#define AR71XX_DDR_REG_PCI_WIN6 0x94 +#define AR71XX_DDR_REG_PCI_WIN7 0x98 +#define AR71XX_DDR_REG_FLUSH_GE0 0x9c +#define AR71XX_DDR_REG_FLUSH_GE1 0xa0 +#define AR71XX_DDR_REG_FLUSH_USB 0xa4 +#define AR71XX_DDR_REG_FLUSH_PCI 0xa8 -#define AR724X_DDR_REG_FLUSH_GE0 0x7c -#define AR724X_DDR_REG_FLUSH_GE1 0x80 -#define AR724X_DDR_REG_FLUSH_USB 0x84 -#define AR724X_DDR_REG_FLUSH_PCIE 0x88 +#define AR724X_DDR_REG_FLUSH_GE0 0x7c +#define AR724X_DDR_REG_FLUSH_GE1 0x80 +#define AR724X_DDR_REG_FLUSH_USB 0x84 +#define AR724X_DDR_REG_FLUSH_PCIE 0x88 -#define AR913X_DDR_REG_FLUSH_GE0 0x7c -#define AR913X_DDR_REG_FLUSH_GE1 0x80 -#define AR913X_DDR_REG_FLUSH_USB 0x84 -#define AR913X_DDR_REG_FLUSH_WMAC 0x88 +#define AR913X_DDR_REG_FLUSH_GE0 0x7c +#define AR913X_DDR_REG_FLUSH_GE1 0x80 +#define AR913X_DDR_REG_FLUSH_USB 0x84 +#define AR913X_DDR_REG_FLUSH_WMAC 0x88 -#define AR933X_DDR_REG_FLUSH_GE0 0x7c -#define AR933X_DDR_REG_FLUSH_GE1 0x80 -#define AR933X_DDR_REG_FLUSH_USB 0x84 -#define AR933X_DDR_REG_FLUSH_WMAC 0x88 -#define AR933X_DDR_REG_DDR2_CONFIG 0x8c -#define AR933X_DDR_REG_EMR2 0x90 -#define AR933X_DDR_REG_EMR3 0x94 -#define AR933X_DDR_REG_BURST 0x98 -#define AR933X_DDR_REG_TIMEOUT_MAX 0x9c -#define AR933X_DDR_REG_TIMEOUT_CNT 0x9c -#define AR933X_DDR_REG_TIMEOUT_ADDR 0x9c +#define AR933X_DDR_REG_FLUSH_GE0 0x7c +#define AR933X_DDR_REG_FLUSH_GE1 0x80 +#define AR933X_DDR_REG_FLUSH_USB 0x84 +#define AR933X_DDR_REG_FLUSH_WMAC 0x88 +#define AR933X_DDR_REG_DDR2_CONFIG 0x8c +#define AR933X_DDR_REG_EMR2 0x90 +#define AR933X_DDR_REG_EMR3 0x94 +#define AR933X_DDR_REG_BURST 0x98 +#define AR933X_DDR_REG_TIMEOUT_MAX 0x9c +#define AR933X_DDR_REG_TIMEOUT_CNT 0x9c +#define AR933X_DDR_REG_TIMEOUT_ADDR 0x9c -#define AR934X_DDR_REG_FLUSH_GE0 0x9c -#define AR934X_DDR_REG_FLUSH_GE1 0xa0 -#define AR934X_DDR_REG_FLUSH_USB 0xa4 -#define AR934X_DDR_REG_FLUSH_PCIE 0xa8 -#define AR934X_DDR_REG_FLUSH_WMAC 0xac +#define AR934X_DDR_REG_FLUSH_GE0 0x9c +#define AR934X_DDR_REG_FLUSH_GE1 0xa0 +#define AR934X_DDR_REG_FLUSH_USB 0xa4 +#define AR934X_DDR_REG_FLUSH_PCIE 0xa8 +#define AR934X_DDR_REG_FLUSH_WMAC 0xac -#define QCA953X_DDR_REG_FLUSH_GE0 0x9c -#define QCA953X_DDR_REG_FLUSH_GE1 0xa0 -#define QCA953X_DDR_REG_FLUSH_USB 0xa4 -#define QCA953X_DDR_REG_FLUSH_PCIE 0xa8 -#define QCA953X_DDR_REG_FLUSH_WMAC 0xac -#define QCA953X_DDR_REG_DDR2_CONFIG 0xb8 -#define QCA953X_DDR_REG_BURST 0xc4 -#define QCA953X_DDR_REG_BURST2 0xc8 -#define QCA953X_DDR_REG_TIMEOUT_MAX 0xcc -#define QCA953X_DDR_REG_CTL_CONF 0x108 -#define QCA953X_DDR_REG_CONFIG3 0x15c +#define QCA953X_DDR_REG_FLUSH_GE0 0x9c +#define QCA953X_DDR_REG_FLUSH_GE1 0xa0 +#define QCA953X_DDR_REG_FLUSH_USB 0xa4 +#define QCA953X_DDR_REG_FLUSH_PCIE 0xa8 +#define QCA953X_DDR_REG_FLUSH_WMAC 0xac +#define QCA953X_DDR_REG_DDR2_CONFIG 0xb8 +#define QCA953X_DDR_REG_BURST 0xc4 +#define QCA953X_DDR_REG_BURST2 0xc8 +#define QCA953X_DDR_REG_TIMEOUT_MAX 0xcc +#define QCA953X_DDR_REG_CTL_CONF 0x108 +#define QCA953X_DDR_REG_CONFIG3 0x15c /* * PLL block */ -#define AR71XX_PLL_REG_CPU_CONFIG 0x00 -#define AR71XX_PLL_REG_SEC_CONFIG 0x04 -#define AR71XX_PLL_REG_ETH0_INT_CLOCK 0x10 -#define AR71XX_PLL_REG_ETH1_INT_CLOCK 0x14 +#define AR71XX_PLL_REG_CPU_CONFIG 0x00 +#define AR71XX_PLL_REG_SEC_CONFIG 0x04 +#define AR71XX_PLL_REG_ETH0_INT_CLOCK 0x10 +#define AR71XX_PLL_REG_ETH1_INT_CLOCK 0x14 -#define AR71XX_PLL_DIV_SHIFT 3 -#define AR71XX_PLL_DIV_MASK 0x1f -#define AR71XX_CPU_DIV_SHIFT 16 -#define AR71XX_CPU_DIV_MASK 0x3 -#define AR71XX_DDR_DIV_SHIFT 18 -#define AR71XX_DDR_DIV_MASK 0x3 -#define AR71XX_AHB_DIV_SHIFT 20 -#define AR71XX_AHB_DIV_MASK 0x7 +#define AR71XX_PLL_DIV_SHIFT 3 +#define AR71XX_PLL_DIV_MASK 0x1f +#define AR71XX_CPU_DIV_SHIFT 16 +#define AR71XX_CPU_DIV_MASK 0x3 +#define AR71XX_DDR_DIV_SHIFT 18 +#define AR71XX_DDR_DIV_MASK 0x3 +#define AR71XX_AHB_DIV_SHIFT 20 +#define AR71XX_AHB_DIV_MASK 0x7 -#define AR71XX_ETH0_PLL_SHIFT 17 -#define AR71XX_ETH1_PLL_SHIFT 19 +#define AR71XX_ETH0_PLL_SHIFT 17 +#define AR71XX_ETH1_PLL_SHIFT 19 -#define AR724X_PLL_REG_CPU_CONFIG 0x00 -#define AR724X_PLL_REG_PCIE_CONFIG 0x18 +#define AR724X_PLL_REG_CPU_CONFIG 0x00 +#define AR724X_PLL_REG_PCIE_CONFIG 0x18 -#define AR724X_PLL_DIV_SHIFT 0 -#define AR724X_PLL_DIV_MASK 0x3ff -#define AR724X_PLL_REF_DIV_SHIFT 10 -#define AR724X_PLL_REF_DIV_MASK 0xf -#define AR724X_AHB_DIV_SHIFT 19 -#define AR724X_AHB_DIV_MASK 0x1 -#define AR724X_DDR_DIV_SHIFT 22 -#define AR724X_DDR_DIV_MASK 0x3 +#define AR724X_PLL_DIV_SHIFT 0 +#define AR724X_PLL_DIV_MASK 0x3ff +#define AR724X_PLL_REF_DIV_SHIFT 10 +#define AR724X_PLL_REF_DIV_MASK 0xf +#define AR724X_AHB_DIV_SHIFT 19 +#define AR724X_AHB_DIV_MASK 0x1 +#define AR724X_DDR_DIV_SHIFT 22 +#define AR724X_DDR_DIV_MASK 0x3 -#define AR7242_PLL_REG_ETH0_INT_CLOCK 0x2c +#define AR7242_PLL_REG_ETH0_INT_CLOCK 0x2c -#define AR913X_PLL_REG_CPU_CONFIG 0x00 -#define AR913X_PLL_REG_ETH_CONFIG 0x04 -#define AR913X_PLL_REG_ETH0_INT_CLOCK 0x14 -#define AR913X_PLL_REG_ETH1_INT_CLOCK 0x18 +#define AR913X_PLL_REG_CPU_CONFIG 0x00 +#define AR913X_PLL_REG_ETH_CONFIG 0x04 +#define AR913X_PLL_REG_ETH0_INT_CLOCK 0x14 +#define AR913X_PLL_REG_ETH1_INT_CLOCK 0x18 -#define AR913X_PLL_DIV_SHIFT 0 -#define AR913X_PLL_DIV_MASK 0x3ff -#define AR913X_DDR_DIV_SHIFT 22 -#define AR913X_DDR_DIV_MASK 0x3 -#define AR913X_AHB_DIV_SHIFT 19 -#define AR913X_AHB_DIV_MASK 0x1 +#define AR913X_PLL_DIV_SHIFT 0 +#define AR913X_PLL_DIV_MASK 0x3ff +#define AR913X_DDR_DIV_SHIFT 22 +#define AR913X_DDR_DIV_MASK 0x3 +#define AR913X_AHB_DIV_SHIFT 19 +#define AR913X_AHB_DIV_MASK 0x1 -#define AR913X_ETH0_PLL_SHIFT 20 -#define AR913X_ETH1_PLL_SHIFT 22 +#define AR913X_ETH0_PLL_SHIFT 20 +#define AR913X_ETH1_PLL_SHIFT 22 -#define AR933X_PLL_CPU_CONFIG_REG 0x00 -#define AR933X_PLL_CLK_CTRL_REG 0x08 -#define AR933X_PLL_DITHER_FRAC_REG 0x10 +#define AR933X_PLL_CPU_CONFIG_REG 0x00 +#define AR933X_PLL_CLK_CTRL_REG 0x08 +#define AR933X_PLL_DITHER_FRAC_REG 0x10 -#define AR933X_PLL_CPU_CONFIG_NINT_SHIFT 10 -#define AR933X_PLL_CPU_CONFIG_NINT_MASK 0x3f -#define AR933X_PLL_CPU_CONFIG_REFDIV_SHIFT 16 -#define AR933X_PLL_CPU_CONFIG_REFDIV_MASK 0x1f -#define AR933X_PLL_CPU_CONFIG_OUTDIV_SHIFT 23 -#define AR933X_PLL_CPU_CONFIG_OUTDIV_MASK 0x7 +#define AR933X_PLL_CPU_CONFIG_NINT_SHIFT 10 +#define AR933X_PLL_CPU_CONFIG_NINT_MASK 0x3f +#define AR933X_PLL_CPU_CONFIG_REFDIV_SHIFT 16 +#define AR933X_PLL_CPU_CONFIG_REFDIV_MASK 0x1f +#define AR933X_PLL_CPU_CONFIG_OUTDIV_SHIFT 23 +#define AR933X_PLL_CPU_CONFIG_OUTDIV_MASK 0x7 -#define AR933X_PLL_CLK_CTRL_BYPASS BIT(2) -#define AR933X_PLL_CLK_CTRL_CPU_POST_DIV_SHIFT 5 -#define AR933X_PLL_CLK_CTRL_CPU_POST_DIV_MASK 0x3 -#define AR933X_PLL_CLK_CTRL_DDR_POST_DIV_SHIFT 10 -#define AR933X_PLL_CLK_CTRL_DDR_POST_DIV_MASK 0x3 -#define AR933X_PLL_CLK_CTRL_AHB_POST_DIV_SHIFT 15 -#define AR933X_PLL_CLK_CTRL_AHB_POST_DIV_MASK 0x7 +#define AR933X_PLL_CLK_CTRL_BYPASS BIT(2) +#define AR933X_PLL_CLK_CTRL_CPU_POST_DIV_SHIFT 5 +#define AR933X_PLL_CLK_CTRL_CPU_POST_DIV_MASK 0x3 +#define AR933X_PLL_CLK_CTRL_DDR_POST_DIV_SHIFT 10 +#define AR933X_PLL_CLK_CTRL_DDR_POST_DIV_MASK 0x3 +#define AR933X_PLL_CLK_CTRL_AHB_POST_DIV_SHIFT 15 +#define AR933X_PLL_CLK_CTRL_AHB_POST_DIV_MASK 0x7 -#define AR934X_PLL_CPU_CONFIG_REG 0x00 -#define AR934X_PLL_DDR_CONFIG_REG 0x04 -#define AR934X_PLL_CPU_DDR_CLK_CTRL_REG 0x08 -#define AR934X_PLL_SWITCH_CLOCK_CONTROL_REG 0x24 -#define AR934X_PLL_ETH_XMII_CONTROL_REG 0x2c +#define AR934X_PLL_CPU_CONFIG_REG 0x00 +#define AR934X_PLL_DDR_CONFIG_REG 0x04 +#define AR934X_PLL_CPU_DDR_CLK_CTRL_REG 0x08 +#define AR934X_PLL_SWITCH_CLOCK_CONTROL_REG 0x24 +#define AR934X_PLL_ETH_XMII_CONTROL_REG 0x2c -#define AR934X_PLL_CPU_CONFIG_NFRAC_SHIFT 0 -#define AR934X_PLL_CPU_CONFIG_NFRAC_MASK 0x3f -#define AR934X_PLL_CPU_CONFIG_NINT_SHIFT 6 -#define AR934X_PLL_CPU_CONFIG_NINT_MASK 0x3f -#define AR934X_PLL_CPU_CONFIG_REFDIV_SHIFT 12 -#define AR934X_PLL_CPU_CONFIG_REFDIV_MASK 0x1f -#define AR934X_PLL_CPU_CONFIG_OUTDIV_SHIFT 19 -#define AR934X_PLL_CPU_CONFIG_OUTDIV_MASK 0x3 +#define AR934X_PLL_CPU_CONFIG_NFRAC_SHIFT 0 +#define AR934X_PLL_CPU_CONFIG_NFRAC_MASK 0x3f +#define AR934X_PLL_CPU_CONFIG_NINT_SHIFT 6 +#define AR934X_PLL_CPU_CONFIG_NINT_MASK 0x3f +#define AR934X_PLL_CPU_CONFIG_REFDIV_SHIFT 12 +#define AR934X_PLL_CPU_CONFIG_REFDIV_MASK 0x1f +#define AR934X_PLL_CPU_CONFIG_OUTDIV_SHIFT 19 +#define AR934X_PLL_CPU_CONFIG_OUTDIV_MASK 0x3 -#define AR934X_PLL_DDR_CONFIG_NFRAC_SHIFT 0 -#define AR934X_PLL_DDR_CONFIG_NFRAC_MASK 0x3ff -#define AR934X_PLL_DDR_CONFIG_NINT_SHIFT 10 -#define AR934X_PLL_DDR_CONFIG_NINT_MASK 0x3f -#define AR934X_PLL_DDR_CONFIG_REFDIV_SHIFT 16 -#define AR934X_PLL_DDR_CONFIG_REFDIV_MASK 0x1f -#define AR934X_PLL_DDR_CONFIG_OUTDIV_SHIFT 23 -#define AR934X_PLL_DDR_CONFIG_OUTDIV_MASK 0x7 +#define AR934X_PLL_DDR_CONFIG_NFRAC_SHIFT 0 +#define AR934X_PLL_DDR_CONFIG_NFRAC_MASK 0x3ff +#define AR934X_PLL_DDR_CONFIG_NINT_SHIFT 10 +#define AR934X_PLL_DDR_CONFIG_NINT_MASK 0x3f +#define AR934X_PLL_DDR_CONFIG_REFDIV_SHIFT 16 +#define AR934X_PLL_DDR_CONFIG_REFDIV_MASK 0x1f +#define AR934X_PLL_DDR_CONFIG_OUTDIV_SHIFT 23 +#define AR934X_PLL_DDR_CONFIG_OUTDIV_MASK 0x7 -#define AR934X_PLL_CLK_CTRL_CPU_PLL_BYPASS BIT(2) -#define AR934X_PLL_CLK_CTRL_DDR_PLL_BYPASS BIT(3) -#define AR934X_PLL_CLK_CTRL_AHB_PLL_BYPASS BIT(4) -#define AR934X_PLL_CLK_CTRL_CPU_POST_DIV_SHIFT 5 -#define AR934X_PLL_CLK_CTRL_CPU_POST_DIV_MASK 0x1f -#define AR934X_PLL_CLK_CTRL_DDR_POST_DIV_SHIFT 10 -#define AR934X_PLL_CLK_CTRL_DDR_POST_DIV_MASK 0x1f -#define AR934X_PLL_CLK_CTRL_AHB_POST_DIV_SHIFT 15 -#define AR934X_PLL_CLK_CTRL_AHB_POST_DIV_MASK 0x1f -#define AR934X_PLL_CLK_CTRL_CPUCLK_FROM_CPUPLL BIT(20) -#define AR934X_PLL_CLK_CTRL_DDRCLK_FROM_DDRPLL BIT(21) -#define AR934X_PLL_CLK_CTRL_AHBCLK_FROM_DDRPLL BIT(24) +#define AR934X_PLL_CLK_CTRL_CPU_PLL_BYPASS BIT(2) +#define AR934X_PLL_CLK_CTRL_DDR_PLL_BYPASS BIT(3) +#define AR934X_PLL_CLK_CTRL_AHB_PLL_BYPASS BIT(4) +#define AR934X_PLL_CLK_CTRL_CPU_POST_DIV_SHIFT 5 +#define AR934X_PLL_CLK_CTRL_CPU_POST_DIV_MASK 0x1f +#define AR934X_PLL_CLK_CTRL_DDR_POST_DIV_SHIFT 10 +#define AR934X_PLL_CLK_CTRL_DDR_POST_DIV_MASK 0x1f +#define AR934X_PLL_CLK_CTRL_AHB_POST_DIV_SHIFT 15 +#define AR934X_PLL_CLK_CTRL_AHB_POST_DIV_MASK 0x1f +#define AR934X_PLL_CLK_CTRL_CPUCLK_FROM_CPUPLL BIT(20) +#define AR934X_PLL_CLK_CTRL_DDRCLK_FROM_DDRPLL BIT(21) +#define AR934X_PLL_CLK_CTRL_AHBCLK_FROM_DDRPLL BIT(24) -#define AR934X_PLL_SWITCH_CLK_CTRL_MDIO_CLK_SEL BIT(6) +#define AR934X_PLL_SWITCH_CLK_CTRL_MDIO_CLK_SEL BIT(6) -#define QCA953X_PLL_CPU_CONFIG_REG 0x00 -#define QCA953X_PLL_DDR_CONFIG_REG 0x04 -#define QCA953X_PLL_CLK_CTRL_REG 0x08 -#define QCA953X_PLL_SWITCH_CLOCK_CONTROL_REG 0x24 -#define QCA953X_PLL_ETH_XMII_CONTROL_REG 0x2c -#define QCA953X_PLL_DDR_DIT_FRAC_REG 0x44 -#define QCA953X_PLL_CPU_DIT_FRAC_REG 0x48 +#define QCA953X_PLL_CPU_CONFIG_REG 0x00 +#define QCA953X_PLL_DDR_CONFIG_REG 0x04 +#define QCA953X_PLL_CLK_CTRL_REG 0x08 +#define QCA953X_PLL_SWITCH_CLOCK_CONTROL_REG 0x24 +#define QCA953X_PLL_ETH_XMII_CONTROL_REG 0x2c +#define QCA953X_PLL_DDR_DIT_FRAC_REG 0x44 +#define QCA953X_PLL_CPU_DIT_FRAC_REG 0x48 -#define QCA953X_PLL_CPU_CONFIG_NFRAC_SHIFT 0 -#define QCA953X_PLL_CPU_CONFIG_NFRAC_MASK 0x3f -#define QCA953X_PLL_CPU_CONFIG_NINT_SHIFT 6 -#define QCA953X_PLL_CPU_CONFIG_NINT_MASK 0x3f -#define QCA953X_PLL_CPU_CONFIG_REFDIV_SHIFT 12 -#define QCA953X_PLL_CPU_CONFIG_REFDIV_MASK 0x1f -#define QCA953X_PLL_CPU_CONFIG_OUTDIV_SHIFT 19 -#define QCA953X_PLL_CPU_CONFIG_OUTDIV_MASK 0x7 +#define QCA953X_PLL_CPU_CONFIG_NFRAC_SHIFT 0 +#define QCA953X_PLL_CPU_CONFIG_NFRAC_MASK 0x3f +#define QCA953X_PLL_CPU_CONFIG_NINT_SHIFT 6 +#define QCA953X_PLL_CPU_CONFIG_NINT_MASK 0x3f +#define QCA953X_PLL_CPU_CONFIG_REFDIV_SHIFT 12 +#define QCA953X_PLL_CPU_CONFIG_REFDIV_MASK 0x1f +#define QCA953X_PLL_CPU_CONFIG_OUTDIV_SHIFT 19 +#define QCA953X_PLL_CPU_CONFIG_OUTDIV_MASK 0x7 -#define QCA953X_PLL_DDR_CONFIG_NFRAC_SHIFT 0 -#define QCA953X_PLL_DDR_CONFIG_NFRAC_MASK 0x3ff -#define QCA953X_PLL_DDR_CONFIG_NINT_SHIFT 10 -#define QCA953X_PLL_DDR_CONFIG_NINT_MASK 0x3f -#define QCA953X_PLL_DDR_CONFIG_REFDIV_SHIFT 16 -#define QCA953X_PLL_DDR_CONFIG_REFDIV_MASK 0x1f -#define QCA953X_PLL_DDR_CONFIG_OUTDIV_SHIFT 23 -#define QCA953X_PLL_DDR_CONFIG_OUTDIV_MASK 0x7 +#define QCA953X_PLL_DDR_CONFIG_NFRAC_SHIFT 0 +#define QCA953X_PLL_DDR_CONFIG_NFRAC_MASK 0x3ff +#define QCA953X_PLL_DDR_CONFIG_NINT_SHIFT 10 +#define QCA953X_PLL_DDR_CONFIG_NINT_MASK 0x3f +#define QCA953X_PLL_DDR_CONFIG_REFDIV_SHIFT 16 +#define QCA953X_PLL_DDR_CONFIG_REFDIV_MASK 0x1f +#define QCA953X_PLL_DDR_CONFIG_OUTDIV_SHIFT 23 +#define QCA953X_PLL_DDR_CONFIG_OUTDIV_MASK 0x7 -#define QCA953X_PLL_CONFIG_PWD BIT(30) +#define QCA953X_PLL_CONFIG_PWD BIT(30) -#define QCA953X_PLL_CLK_CTRL_CPU_PLL_BYPASS BIT(2) -#define QCA953X_PLL_CLK_CTRL_DDR_PLL_BYPASS BIT(3) -#define QCA953X_PLL_CLK_CTRL_AHB_PLL_BYPASS BIT(4) -#define QCA953X_PLL_CLK_CTRL_CPU_POST_DIV_SHIFT 5 -#define QCA953X_PLL_CLK_CTRL_CPU_POST_DIV_MASK 0x1f -#define QCA953X_PLL_CLK_CTRL_DDR_POST_DIV_SHIFT 10 -#define QCA953X_PLL_CLK_CTRL_DDR_POST_DIV_MASK 0x1f -#define QCA953X_PLL_CLK_CTRL_AHB_POST_DIV_SHIFT 15 -#define QCA953X_PLL_CLK_CTRL_AHB_POST_DIV_MASK 0x1f -#define QCA953X_PLL_CLK_CTRL_CPUCLK_FROM_CPUPLL BIT(20) -#define QCA953X_PLL_CLK_CTRL_DDRCLK_FROM_DDRPLL BIT(21) -#define QCA953X_PLL_CLK_CTRL_AHBCLK_FROM_DDRPLL BIT(24) +#define QCA953X_PLL_CLK_CTRL_CPU_PLL_BYPASS BIT(2) +#define QCA953X_PLL_CLK_CTRL_DDR_PLL_BYPASS BIT(3) +#define QCA953X_PLL_CLK_CTRL_AHB_PLL_BYPASS BIT(4) +#define QCA953X_PLL_CLK_CTRL_CPU_POST_DIV_SHIFT 5 +#define QCA953X_PLL_CLK_CTRL_CPU_POST_DIV_MASK 0x1f +#define QCA953X_PLL_CLK_CTRL_DDR_POST_DIV_SHIFT 10 +#define QCA953X_PLL_CLK_CTRL_DDR_POST_DIV_MASK 0x1f +#define QCA953X_PLL_CLK_CTRL_AHB_POST_DIV_SHIFT 15 +#define QCA953X_PLL_CLK_CTRL_AHB_POST_DIV_MASK 0x1f +#define QCA953X_PLL_CLK_CTRL_CPUCLK_FROM_CPUPLL BIT(20) +#define QCA953X_PLL_CLK_CTRL_DDRCLK_FROM_DDRPLL BIT(21) +#define QCA953X_PLL_CLK_CTRL_AHBCLK_FROM_DDRPLL BIT(24) -#define QCA953X_PLL_CPU_DIT_FRAC_MAX_SHIFT 0 -#define QCA953X_PLL_CPU_DIT_FRAC_MAX_MASK 0x3f -#define QCA953X_PLL_CPU_DIT_FRAC_MIN_SHIFT 6 -#define QCA953X_PLL_CPU_DIT_FRAC_MIN_MASK 0x3f -#define QCA953X_PLL_CPU_DIT_FRAC_STEP_SHIFT 12 -#define QCA953X_PLL_CPU_DIT_FRAC_STEP_MASK 0x3f -#define QCA953X_PLL_CPU_DIT_UPD_CNT_SHIFT 18 -#define QCA953X_PLL_CPU_DIT_UPD_CNT_MASK 0x3f +#define QCA953X_PLL_CPU_DIT_FRAC_MAX_SHIFT 0 +#define QCA953X_PLL_CPU_DIT_FRAC_MAX_MASK 0x3f +#define QCA953X_PLL_CPU_DIT_FRAC_MIN_SHIFT 6 +#define QCA953X_PLL_CPU_DIT_FRAC_MIN_MASK 0x3f +#define QCA953X_PLL_CPU_DIT_FRAC_STEP_SHIFT 12 +#define QCA953X_PLL_CPU_DIT_FRAC_STEP_MASK 0x3f +#define QCA953X_PLL_CPU_DIT_UPD_CNT_SHIFT 18 +#define QCA953X_PLL_CPU_DIT_UPD_CNT_MASK 0x3f -#define QCA953X_PLL_DDR_DIT_FRAC_MAX_SHIFT 0 -#define QCA953X_PLL_DDR_DIT_FRAC_MAX_MASK 0x3ff -#define QCA953X_PLL_DDR_DIT_FRAC_MIN_SHIFT 9 -#define QCA953X_PLL_DDR_DIT_FRAC_MIN_MASK 0x3ff -#define QCA953X_PLL_DDR_DIT_FRAC_STEP_SHIFT 20 -#define QCA953X_PLL_DDR_DIT_FRAC_STEP_MASK 0x3f -#define QCA953X_PLL_DDR_DIT_UPD_CNT_SHIFT 27 -#define QCA953X_PLL_DDR_DIT_UPD_CNT_MASK 0x3f +#define QCA953X_PLL_DDR_DIT_FRAC_MAX_SHIFT 0 +#define QCA953X_PLL_DDR_DIT_FRAC_MAX_MASK 0x3ff +#define QCA953X_PLL_DDR_DIT_FRAC_MIN_SHIFT 9 +#define QCA953X_PLL_DDR_DIT_FRAC_MIN_MASK 0x3ff +#define QCA953X_PLL_DDR_DIT_FRAC_STEP_SHIFT 20 +#define QCA953X_PLL_DDR_DIT_FRAC_STEP_MASK 0x3f +#define QCA953X_PLL_DDR_DIT_UPD_CNT_SHIFT 27 +#define QCA953X_PLL_DDR_DIT_UPD_CNT_MASK 0x3f -#define QCA953X_PLL_DIT_FRAC_EN BIT(31) +#define QCA953X_PLL_DIT_FRAC_EN BIT(31) -#define QCA955X_PLL_CPU_CONFIG_REG 0x00 -#define QCA955X_PLL_DDR_CONFIG_REG 0x04 -#define QCA955X_PLL_CLK_CTRL_REG 0x08 -#define QCA955X_PLL_ETH_XMII_CONTROL_REG 0x28 -#define QCA955X_PLL_ETH_SGMII_CONTROL_REG 0x48 +#define QCA955X_PLL_CPU_CONFIG_REG 0x00 +#define QCA955X_PLL_DDR_CONFIG_REG 0x04 +#define QCA955X_PLL_CLK_CTRL_REG 0x08 +#define QCA955X_PLL_ETH_XMII_CONTROL_REG 0x28 +#define QCA955X_PLL_ETH_SGMII_CONTROL_REG 0x48 -#define QCA955X_PLL_CPU_CONFIG_NFRAC_SHIFT 0 -#define QCA955X_PLL_CPU_CONFIG_NFRAC_MASK 0x3f -#define QCA955X_PLL_CPU_CONFIG_NINT_SHIFT 6 -#define QCA955X_PLL_CPU_CONFIG_NINT_MASK 0x3f -#define QCA955X_PLL_CPU_CONFIG_REFDIV_SHIFT 12 -#define QCA955X_PLL_CPU_CONFIG_REFDIV_MASK 0x1f -#define QCA955X_PLL_CPU_CONFIG_OUTDIV_SHIFT 19 -#define QCA955X_PLL_CPU_CONFIG_OUTDIV_MASK 0x3 +#define QCA955X_PLL_CPU_CONFIG_NFRAC_SHIFT 0 +#define QCA955X_PLL_CPU_CONFIG_NFRAC_MASK 0x3f +#define QCA955X_PLL_CPU_CONFIG_NINT_SHIFT 6 +#define QCA955X_PLL_CPU_CONFIG_NINT_MASK 0x3f +#define QCA955X_PLL_CPU_CONFIG_REFDIV_SHIFT 12 +#define QCA955X_PLL_CPU_CONFIG_REFDIV_MASK 0x1f +#define QCA955X_PLL_CPU_CONFIG_OUTDIV_SHIFT 19 +#define QCA955X_PLL_CPU_CONFIG_OUTDIV_MASK 0x3 -#define QCA955X_PLL_DDR_CONFIG_NFRAC_SHIFT 0 -#define QCA955X_PLL_DDR_CONFIG_NFRAC_MASK 0x3ff -#define QCA955X_PLL_DDR_CONFIG_NINT_SHIFT 10 -#define QCA955X_PLL_DDR_CONFIG_NINT_MASK 0x3f -#define QCA955X_PLL_DDR_CONFIG_REFDIV_SHIFT 16 -#define QCA955X_PLL_DDR_CONFIG_REFDIV_MASK 0x1f -#define QCA955X_PLL_DDR_CONFIG_OUTDIV_SHIFT 23 -#define QCA955X_PLL_DDR_CONFIG_OUTDIV_MASK 0x7 +#define QCA955X_PLL_DDR_CONFIG_NFRAC_SHIFT 0 +#define QCA955X_PLL_DDR_CONFIG_NFRAC_MASK 0x3ff +#define QCA955X_PLL_DDR_CONFIG_NINT_SHIFT 10 +#define QCA955X_PLL_DDR_CONFIG_NINT_MASK 0x3f +#define QCA955X_PLL_DDR_CONFIG_REFDIV_SHIFT 16 +#define QCA955X_PLL_DDR_CONFIG_REFDIV_MASK 0x1f +#define QCA955X_PLL_DDR_CONFIG_OUTDIV_SHIFT 23 +#define QCA955X_PLL_DDR_CONFIG_OUTDIV_MASK 0x7 -#define QCA955X_PLL_CLK_CTRL_CPU_PLL_BYPASS BIT(2) -#define QCA955X_PLL_CLK_CTRL_DDR_PLL_BYPASS BIT(3) -#define QCA955X_PLL_CLK_CTRL_AHB_PLL_BYPASS BIT(4) -#define QCA955X_PLL_CLK_CTRL_CPU_POST_DIV_SHIFT 5 -#define QCA955X_PLL_CLK_CTRL_CPU_POST_DIV_MASK 0x1f -#define QCA955X_PLL_CLK_CTRL_DDR_POST_DIV_SHIFT 10 -#define QCA955X_PLL_CLK_CTRL_DDR_POST_DIV_MASK 0x1f -#define QCA955X_PLL_CLK_CTRL_AHB_POST_DIV_SHIFT 15 -#define QCA955X_PLL_CLK_CTRL_AHB_POST_DIV_MASK 0x1f -#define QCA955X_PLL_CLK_CTRL_CPUCLK_FROM_CPUPLL BIT(20) -#define QCA955X_PLL_CLK_CTRL_DDRCLK_FROM_DDRPLL BIT(21) -#define QCA955X_PLL_CLK_CTRL_AHBCLK_FROM_DDRPLL BIT(24) +#define QCA955X_PLL_CLK_CTRL_CPU_PLL_BYPASS BIT(2) +#define QCA955X_PLL_CLK_CTRL_DDR_PLL_BYPASS BIT(3) +#define QCA955X_PLL_CLK_CTRL_AHB_PLL_BYPASS BIT(4) +#define QCA955X_PLL_CLK_CTRL_CPU_POST_DIV_SHIFT 5 +#define QCA955X_PLL_CLK_CTRL_CPU_POST_DIV_MASK 0x1f +#define QCA955X_PLL_CLK_CTRL_DDR_POST_DIV_SHIFT 10 +#define QCA955X_PLL_CLK_CTRL_DDR_POST_DIV_MASK 0x1f +#define QCA955X_PLL_CLK_CTRL_AHB_POST_DIV_SHIFT 15 +#define QCA955X_PLL_CLK_CTRL_AHB_POST_DIV_MASK 0x1f +#define QCA955X_PLL_CLK_CTRL_CPUCLK_FROM_CPUPLL BIT(20) +#define QCA955X_PLL_CLK_CTRL_DDRCLK_FROM_DDRPLL BIT(21) +#define QCA955X_PLL_CLK_CTRL_AHBCLK_FROM_DDRPLL BIT(24) -#define QCA956X_PLL_CPU_CONFIG_REG 0x00 -#define QCA956X_PLL_CPU_CONFIG1_REG 0x04 -#define QCA956X_PLL_DDR_CONFIG_REG 0x08 -#define QCA956X_PLL_DDR_CONFIG1_REG 0x0c -#define QCA956X_PLL_CLK_CTRL_REG 0x10 +#define QCA956X_PLL_CPU_CONFIG_REG 0x00 +#define QCA956X_PLL_CPU_CONFIG1_REG 0x04 +#define QCA956X_PLL_DDR_CONFIG_REG 0x08 +#define QCA956X_PLL_DDR_CONFIG1_REG 0x0c +#define QCA956X_PLL_CLK_CTRL_REG 0x10 -#define QCA956X_PLL_CPU_CONFIG_REFDIV_SHIFT 12 -#define QCA956X_PLL_CPU_CONFIG_REFDIV_MASK 0x1f -#define QCA956X_PLL_CPU_CONFIG_OUTDIV_SHIFT 19 -#define QCA956X_PLL_CPU_CONFIG_OUTDIV_MASK 0x7 +#define QCA956X_PLL_CPU_CONFIG_REFDIV_SHIFT 12 +#define QCA956X_PLL_CPU_CONFIG_REFDIV_MASK 0x1f +#define QCA956X_PLL_CPU_CONFIG_OUTDIV_SHIFT 19 +#define QCA956X_PLL_CPU_CONFIG_OUTDIV_MASK 0x7 -#define QCA956X_PLL_CPU_CONFIG1_NFRAC_L_SHIFT 0 -#define QCA956X_PLL_CPU_CONFIG1_NFRAC_L_MASK 0x1f -#define QCA956X_PLL_CPU_CONFIG1_NFRAC_H_SHIFT 5 -#define QCA956X_PLL_CPU_CONFIG1_NFRAC_H_MASK 0x3fff -#define QCA956X_PLL_CPU_CONFIG1_NINT_SHIFT 18 -#define QCA956X_PLL_CPU_CONFIG1_NINT_MASK 0x1ff +#define QCA956X_PLL_CPU_CONFIG1_NFRAC_L_SHIFT 0 +#define QCA956X_PLL_CPU_CONFIG1_NFRAC_L_MASK 0x1f +#define QCA956X_PLL_CPU_CONFIG1_NFRAC_H_SHIFT 5 +#define QCA956X_PLL_CPU_CONFIG1_NFRAC_H_MASK 0x3fff +#define QCA956X_PLL_CPU_CONFIG1_NINT_SHIFT 18 +#define QCA956X_PLL_CPU_CONFIG1_NINT_MASK 0x1ff -#define QCA956X_PLL_DDR_CONFIG_REFDIV_SHIFT 16 -#define QCA956X_PLL_DDR_CONFIG_REFDIV_MASK 0x1f -#define QCA956X_PLL_DDR_CONFIG_OUTDIV_SHIFT 23 -#define QCA956X_PLL_DDR_CONFIG_OUTDIV_MASK 0x7 +#define QCA956X_PLL_DDR_CONFIG_REFDIV_SHIFT 16 +#define QCA956X_PLL_DDR_CONFIG_REFDIV_MASK 0x1f +#define QCA956X_PLL_DDR_CONFIG_OUTDIV_SHIFT 23 +#define QCA956X_PLL_DDR_CONFIG_OUTDIV_MASK 0x7 -#define QCA956X_PLL_DDR_CONFIG1_NFRAC_L_SHIFT 0 -#define QCA956X_PLL_DDR_CONFIG1_NFRAC_L_MASK 0x1f -#define QCA956X_PLL_DDR_CONFIG1_NFRAC_H_SHIFT 5 -#define QCA956X_PLL_DDR_CONFIG1_NFRAC_H_MASK 0x3fff -#define QCA956X_PLL_DDR_CONFIG1_NINT_SHIFT 18 -#define QCA956X_PLL_DDR_CONFIG1_NINT_MASK 0x1ff +#define QCA956X_PLL_DDR_CONFIG1_NFRAC_L_SHIFT 0 +#define QCA956X_PLL_DDR_CONFIG1_NFRAC_L_MASK 0x1f +#define QCA956X_PLL_DDR_CONFIG1_NFRAC_H_SHIFT 5 +#define QCA956X_PLL_DDR_CONFIG1_NFRAC_H_MASK 0x3fff +#define QCA956X_PLL_DDR_CONFIG1_NINT_SHIFT 18 +#define QCA956X_PLL_DDR_CONFIG1_NINT_MASK 0x1ff -#define QCA956X_PLL_CLK_CTRL_CPU_PLL_BYPASS BIT(2) -#define QCA956X_PLL_CLK_CTRL_DDR_PLL_BYPASS BIT(3) -#define QCA956X_PLL_CLK_CTRL_AHB_PLL_BYPASS BIT(4) -#define QCA956X_PLL_CLK_CTRL_CPU_POST_DIV_SHIFT 5 -#define QCA956X_PLL_CLK_CTRL_CPU_POST_DIV_MASK 0x1f -#define QCA956X_PLL_CLK_CTRL_DDR_POST_DIV_SHIFT 10 -#define QCA956X_PLL_CLK_CTRL_DDR_POST_DIV_MASK 0x1f -#define QCA956X_PLL_CLK_CTRL_AHB_POST_DIV_SHIFT 15 -#define QCA956X_PLL_CLK_CTRL_AHB_POST_DIV_MASK 0x1f -#define QCA956X_PLL_CLK_CTRL_CPU_DDRCLK_FROM_DDRPLL BIT(20) -#define QCA956X_PLL_CLK_CTRL_CPU_DDRCLK_FROM_CPUPLL BIT(21) -#define QCA956X_PLL_CLK_CTRL_AHBCLK_FROM_DDRPLL BIT(24) +#define QCA956X_PLL_CLK_CTRL_CPU_PLL_BYPASS BIT(2) +#define QCA956X_PLL_CLK_CTRL_DDR_PLL_BYPASS BIT(3) +#define QCA956X_PLL_CLK_CTRL_AHB_PLL_BYPASS BIT(4) +#define QCA956X_PLL_CLK_CTRL_CPU_POST_DIV_SHIFT 5 +#define QCA956X_PLL_CLK_CTRL_CPU_POST_DIV_MASK 0x1f +#define QCA956X_PLL_CLK_CTRL_DDR_POST_DIV_SHIFT 10 +#define QCA956X_PLL_CLK_CTRL_DDR_POST_DIV_MASK 0x1f +#define QCA956X_PLL_CLK_CTRL_AHB_POST_DIV_SHIFT 15 +#define QCA956X_PLL_CLK_CTRL_AHB_POST_DIV_MASK 0x1f +#define QCA956X_PLL_CLK_CTRL_CPU_DDRCLK_FROM_DDRPLL BIT(20) +#define QCA956X_PLL_CLK_CTRL_CPU_DDRCLK_FROM_CPUPLL BIT(21) +#define QCA956X_PLL_CLK_CTRL_AHBCLK_FROM_DDRPLL BIT(24) /* * USB_CONFIG block */ -#define AR71XX_USB_CTRL_REG_FLADJ 0x00 -#define AR71XX_USB_CTRL_REG_CONFIG 0x04 +#define AR71XX_USB_CTRL_REG_FLADJ 0x00 +#define AR71XX_USB_CTRL_REG_CONFIG 0x04 /* * RESET block */ -#define AR71XX_RESET_REG_TIMER 0x00 -#define AR71XX_RESET_REG_TIMER_RELOAD 0x04 -#define AR71XX_RESET_REG_WDOG_CTRL 0x08 -#define AR71XX_RESET_REG_WDOG 0x0c -#define AR71XX_RESET_REG_MISC_INT_STATUS 0x10 -#define AR71XX_RESET_REG_MISC_INT_ENABLE 0x14 -#define AR71XX_RESET_REG_PCI_INT_STATUS 0x18 -#define AR71XX_RESET_REG_PCI_INT_ENABLE 0x1c -#define AR71XX_RESET_REG_GLOBAL_INT_STATUS 0x20 -#define AR71XX_RESET_REG_RESET_MODULE 0x24 -#define AR71XX_RESET_REG_PERFC_CTRL 0x2c -#define AR71XX_RESET_REG_PERFC0 0x30 -#define AR71XX_RESET_REG_PERFC1 0x34 -#define AR71XX_RESET_REG_REV_ID 0x90 +#define AR71XX_RESET_REG_TIMER 0x00 +#define AR71XX_RESET_REG_TIMER_RELOAD 0x04 +#define AR71XX_RESET_REG_WDOG_CTRL 0x08 +#define AR71XX_RESET_REG_WDOG 0x0c +#define AR71XX_RESET_REG_MISC_INT_STATUS 0x10 +#define AR71XX_RESET_REG_MISC_INT_ENABLE 0x14 +#define AR71XX_RESET_REG_PCI_INT_STATUS 0x18 +#define AR71XX_RESET_REG_PCI_INT_ENABLE 0x1c +#define AR71XX_RESET_REG_GLOBAL_INT_STATUS 0x20 +#define AR71XX_RESET_REG_RESET_MODULE 0x24 +#define AR71XX_RESET_REG_PERFC_CTRL 0x2c +#define AR71XX_RESET_REG_PERFC0 0x30 +#define AR71XX_RESET_REG_PERFC1 0x34 +#define AR71XX_RESET_REG_REV_ID 0x90 -#define AR913X_RESET_REG_GLOBAL_INT_STATUS 0x18 -#define AR913X_RESET_REG_RESET_MODULE 0x1c -#define AR913X_RESET_REG_PERF_CTRL 0x20 -#define AR913X_RESET_REG_PERFC0 0x24 -#define AR913X_RESET_REG_PERFC1 0x28 +#define AR913X_RESET_REG_GLOBAL_INT_STATUS 0x18 +#define AR913X_RESET_REG_RESET_MODULE 0x1c +#define AR913X_RESET_REG_PERF_CTRL 0x20 +#define AR913X_RESET_REG_PERFC0 0x24 +#define AR913X_RESET_REG_PERFC1 0x28 -#define AR724X_RESET_REG_RESET_MODULE 0x1c +#define AR724X_RESET_REG_RESET_MODULE 0x1c -#define AR933X_RESET_REG_RESET_MODULE 0x1c -#define AR933X_RESET_REG_BOOTSTRAP 0xac +#define AR933X_RESET_REG_RESET_MODULE 0x1c +#define AR933X_RESET_REG_BOOTSTRAP 0xac -#define AR934X_RESET_REG_RESET_MODULE 0x1c -#define AR934X_RESET_REG_BOOTSTRAP 0xb0 -#define AR934X_RESET_REG_PCIE_WMAC_INT_STATUS 0xac +#define AR934X_RESET_REG_RESET_MODULE 0x1c +#define AR934X_RESET_REG_BOOTSTRAP 0xb0 +#define AR934X_RESET_REG_PCIE_WMAC_INT_STATUS 0xac -#define QCA953X_RESET_REG_RESET_MODULE 0x1c -#define QCA953X_RESET_REG_BOOTSTRAP 0xb0 -#define QCA953X_RESET_REG_PCIE_WMAC_INT_STATUS 0xac +#define QCA953X_RESET_REG_RESET_MODULE 0x1c +#define QCA953X_RESET_REG_BOOTSTRAP 0xb0 +#define QCA953X_RESET_REG_PCIE_WMAC_INT_STATUS 0xac -#define QCA955X_RESET_REG_RESET_MODULE 0x1c -#define QCA955X_RESET_REG_BOOTSTRAP 0xb0 -#define QCA955X_RESET_REG_EXT_INT_STATUS 0xac +#define QCA955X_RESET_REG_RESET_MODULE 0x1c +#define QCA955X_RESET_REG_BOOTSTRAP 0xb0 +#define QCA955X_RESET_REG_EXT_INT_STATUS 0xac -#define QCA956X_RESET_REG_RESET_MODULE 0x1c -#define QCA956X_RESET_REG_BOOTSTRAP 0xb0 -#define QCA956X_RESET_REG_EXT_INT_STATUS 0xac +#define QCA956X_RESET_REG_RESET_MODULE 0x1c +#define QCA956X_RESET_REG_BOOTSTRAP 0xb0 +#define QCA956X_RESET_REG_EXT_INT_STATUS 0xac -#define MISC_INT_MIPS_SI_TIMERINT_MASK BIT(28) -#define MISC_INT_ETHSW BIT(12) -#define MISC_INT_TIMER4 BIT(10) -#define MISC_INT_TIMER3 BIT(9) -#define MISC_INT_TIMER2 BIT(8) -#define MISC_INT_DMA BIT(7) -#define MISC_INT_OHCI BIT(6) -#define MISC_INT_PERFC BIT(5) -#define MISC_INT_WDOG BIT(4) -#define MISC_INT_UART BIT(3) -#define MISC_INT_GPIO BIT(2) -#define MISC_INT_ERROR BIT(1) -#define MISC_INT_TIMER BIT(0) +#define MISC_INT_MIPS_SI_TIMERINT_MASK BIT(28) +#define MISC_INT_ETHSW BIT(12) +#define MISC_INT_TIMER4 BIT(10) +#define MISC_INT_TIMER3 BIT(9) +#define MISC_INT_TIMER2 BIT(8) +#define MISC_INT_DMA BIT(7) +#define MISC_INT_OHCI BIT(6) +#define MISC_INT_PERFC BIT(5) +#define MISC_INT_WDOG BIT(4) +#define MISC_INT_UART BIT(3) +#define MISC_INT_GPIO BIT(2) +#define MISC_INT_ERROR BIT(1) +#define MISC_INT_TIMER BIT(0) -#define AR71XX_RESET_EXTERNAL BIT(28) -#define AR71XX_RESET_FULL_CHIP BIT(24) -#define AR71XX_RESET_CPU_NMI BIT(21) -#define AR71XX_RESET_CPU_COLD BIT(20) -#define AR71XX_RESET_DMA BIT(19) -#define AR71XX_RESET_SLIC BIT(18) -#define AR71XX_RESET_STEREO BIT(17) -#define AR71XX_RESET_DDR BIT(16) -#define AR71XX_RESET_GE1_MAC BIT(13) -#define AR71XX_RESET_GE1_PHY BIT(12) -#define AR71XX_RESET_USBSUS_OVERRIDE BIT(10) -#define AR71XX_RESET_GE0_MAC BIT(9) -#define AR71XX_RESET_GE0_PHY BIT(8) -#define AR71XX_RESET_USB_OHCI_DLL BIT(6) -#define AR71XX_RESET_USB_HOST BIT(5) -#define AR71XX_RESET_USB_PHY BIT(4) -#define AR71XX_RESET_PCI_BUS BIT(1) -#define AR71XX_RESET_PCI_CORE BIT(0) +#define AR71XX_RESET_EXTERNAL BIT(28) +#define AR71XX_RESET_FULL_CHIP BIT(24) +#define AR71XX_RESET_CPU_NMI BIT(21) +#define AR71XX_RESET_CPU_COLD BIT(20) +#define AR71XX_RESET_DMA BIT(19) +#define AR71XX_RESET_SLIC BIT(18) +#define AR71XX_RESET_STEREO BIT(17) +#define AR71XX_RESET_DDR BIT(16) +#define AR71XX_RESET_GE1_MAC BIT(13) +#define AR71XX_RESET_GE1_PHY BIT(12) +#define AR71XX_RESET_USBSUS_OVERRIDE BIT(10) +#define AR71XX_RESET_GE0_MAC BIT(9) +#define AR71XX_RESET_GE0_PHY BIT(8) +#define AR71XX_RESET_USB_OHCI_DLL BIT(6) +#define AR71XX_RESET_USB_HOST BIT(5) +#define AR71XX_RESET_USB_PHY BIT(4) +#define AR71XX_RESET_PCI_BUS BIT(1) +#define AR71XX_RESET_PCI_CORE BIT(0) -#define AR7240_RESET_USB_HOST BIT(5) -#define AR7240_RESET_OHCI_DLL BIT(3) +#define AR7240_RESET_USB_HOST BIT(5) +#define AR7240_RESET_OHCI_DLL BIT(3) -#define AR724X_RESET_GE1_MDIO BIT(23) -#define AR724X_RESET_GE0_MDIO BIT(22) -#define AR724X_RESET_PCIE_PHY_SERIAL BIT(10) -#define AR724X_RESET_PCIE_PHY BIT(7) -#define AR724X_RESET_PCIE BIT(6) -#define AR724X_RESET_USB_HOST BIT(5) -#define AR724X_RESET_USB_PHY BIT(4) -#define AR724X_RESET_USBSUS_OVERRIDE BIT(3) +#define AR724X_RESET_GE1_MDIO BIT(23) +#define AR724X_RESET_GE0_MDIO BIT(22) +#define AR724X_RESET_PCIE_PHY_SERIAL BIT(10) +#define AR724X_RESET_PCIE_PHY BIT(7) +#define AR724X_RESET_PCIE BIT(6) +#define AR724X_RESET_USB_HOST BIT(5) +#define AR724X_RESET_USB_PHY BIT(4) +#define AR724X_RESET_USBSUS_OVERRIDE BIT(3) -#define AR913X_RESET_AMBA2WMAC BIT(22) -#define AR913X_RESET_USBSUS_OVERRIDE BIT(10) -#define AR913X_RESET_USB_HOST BIT(5) -#define AR913X_RESET_USB_PHY BIT(4) +#define AR913X_RESET_AMBA2WMAC BIT(22) +#define AR913X_RESET_USBSUS_OVERRIDE BIT(10) +#define AR913X_RESET_USB_HOST BIT(5) +#define AR913X_RESET_USB_PHY BIT(4) -#define AR933X_RESET_GE1_MDIO BIT(23) -#define AR933X_RESET_GE0_MDIO BIT(22) -#define AR933X_RESET_GE1_MAC BIT(13) -#define AR933X_RESET_WMAC BIT(11) -#define AR933X_RESET_GE0_MAC BIT(9) -#define AR933X_RESET_USB_HOST BIT(5) -#define AR933X_RESET_USB_PHY BIT(4) -#define AR933X_RESET_USBSUS_OVERRIDE BIT(3) +#define AR933X_RESET_GE1_MDIO BIT(23) +#define AR933X_RESET_GE0_MDIO BIT(22) +#define AR933X_RESET_GE1_MAC BIT(13) +#define AR933X_RESET_WMAC BIT(11) +#define AR933X_RESET_GE0_MAC BIT(9) +#define AR933X_RESET_USB_HOST BIT(5) +#define AR933X_RESET_USB_PHY BIT(4) +#define AR933X_RESET_USBSUS_OVERRIDE BIT(3) -#define AR934X_RESET_HOST BIT(31) -#define AR934X_RESET_SLIC BIT(30) -#define AR934X_RESET_HDMA BIT(29) -#define AR934X_RESET_EXTERNAL BIT(28) -#define AR934X_RESET_RTC BIT(27) -#define AR934X_RESET_PCIE_EP_INT BIT(26) -#define AR934X_RESET_CHKSUM_ACC BIT(25) -#define AR934X_RESET_FULL_CHIP BIT(24) -#define AR934X_RESET_GE1_MDIO BIT(23) -#define AR934X_RESET_GE0_MDIO BIT(22) -#define AR934X_RESET_CPU_NMI BIT(21) -#define AR934X_RESET_CPU_COLD BIT(20) -#define AR934X_RESET_HOST_RESET_INT BIT(19) -#define AR934X_RESET_PCIE_EP BIT(18) -#define AR934X_RESET_UART1 BIT(17) -#define AR934X_RESET_DDR BIT(16) -#define AR934X_RESET_USB_PHY_PLL_PWD_EXT BIT(15) -#define AR934X_RESET_NANDF BIT(14) -#define AR934X_RESET_GE1_MAC BIT(13) -#define AR934X_RESET_ETH_SWITCH_ANALOG BIT(12) -#define AR934X_RESET_USB_PHY_ANALOG BIT(11) -#define AR934X_RESET_HOST_DMA_INT BIT(10) -#define AR934X_RESET_GE0_MAC BIT(9) -#define AR934X_RESET_ETH_SWITCH BIT(8) -#define AR934X_RESET_PCIE_PHY BIT(7) -#define AR934X_RESET_PCIE BIT(6) -#define AR934X_RESET_USB_HOST BIT(5) -#define AR934X_RESET_USB_PHY BIT(4) -#define AR934X_RESET_USBSUS_OVERRIDE BIT(3) -#define AR934X_RESET_LUT BIT(2) -#define AR934X_RESET_MBOX BIT(1) -#define AR934X_RESET_I2S BIT(0) +#define AR934X_RESET_HOST BIT(31) +#define AR934X_RESET_SLIC BIT(30) +#define AR934X_RESET_HDMA BIT(29) +#define AR934X_RESET_EXTERNAL BIT(28) +#define AR934X_RESET_RTC BIT(27) +#define AR934X_RESET_PCIE_EP_INT BIT(26) +#define AR934X_RESET_CHKSUM_ACC BIT(25) +#define AR934X_RESET_FULL_CHIP BIT(24) +#define AR934X_RESET_GE1_MDIO BIT(23) +#define AR934X_RESET_GE0_MDIO BIT(22) +#define AR934X_RESET_CPU_NMI BIT(21) +#define AR934X_RESET_CPU_COLD BIT(20) +#define AR934X_RESET_HOST_RESET_INT BIT(19) +#define AR934X_RESET_PCIE_EP BIT(18) +#define AR934X_RESET_UART1 BIT(17) +#define AR934X_RESET_DDR BIT(16) +#define AR934X_RESET_USB_PHY_PLL_PWD_EXT BIT(15) +#define AR934X_RESET_NANDF BIT(14) +#define AR934X_RESET_GE1_MAC BIT(13) +#define AR934X_RESET_ETH_SWITCH_ANALOG BIT(12) +#define AR934X_RESET_USB_PHY_ANALOG BIT(11) +#define AR934X_RESET_HOST_DMA_INT BIT(10) +#define AR934X_RESET_GE0_MAC BIT(9) +#define AR934X_RESET_ETH_SWITCH BIT(8) +#define AR934X_RESET_PCIE_PHY BIT(7) +#define AR934X_RESET_PCIE BIT(6) +#define AR934X_RESET_USB_HOST BIT(5) +#define AR934X_RESET_USB_PHY BIT(4) +#define AR934X_RESET_USBSUS_OVERRIDE BIT(3) +#define AR934X_RESET_LUT BIT(2) +#define AR934X_RESET_MBOX BIT(1) +#define AR934X_RESET_I2S BIT(0) -#define QCA953X_RESET_USB_EXT_PWR BIT(29) -#define QCA953X_RESET_EXTERNAL BIT(28) -#define QCA953X_RESET_RTC BIT(27) -#define QCA953X_RESET_FULL_CHIP BIT(24) -#define QCA953X_RESET_GE1_MDIO BIT(23) -#define QCA953X_RESET_GE0_MDIO BIT(22) -#define QCA953X_RESET_CPU_NMI BIT(21) -#define QCA953X_RESET_CPU_COLD BIT(20) -#define QCA953X_RESET_DDR BIT(16) -#define QCA953X_RESET_USB_PHY_PLL_PWD_EXT BIT(15) -#define QCA953X_RESET_GE1_MAC BIT(13) -#define QCA953X_RESET_ETH_SWITCH_ANALOG BIT(12) -#define QCA953X_RESET_USB_PHY_ANALOG BIT(11) -#define QCA953X_RESET_GE0_MAC BIT(9) -#define QCA953X_RESET_ETH_SWITCH BIT(8) -#define QCA953X_RESET_PCIE_PHY BIT(7) -#define QCA953X_RESET_PCIE BIT(6) -#define QCA953X_RESET_USB_HOST BIT(5) -#define QCA953X_RESET_USB_PHY BIT(4) -#define QCA953X_RESET_USBSUS_OVERRIDE BIT(3) +#define QCA953X_RESET_USB_EXT_PWR BIT(29) +#define QCA953X_RESET_EXTERNAL BIT(28) +#define QCA953X_RESET_RTC BIT(27) +#define QCA953X_RESET_FULL_CHIP BIT(24) +#define QCA953X_RESET_GE1_MDIO BIT(23) +#define QCA953X_RESET_GE0_MDIO BIT(22) +#define QCA953X_RESET_CPU_NMI BIT(21) +#define QCA953X_RESET_CPU_COLD BIT(20) +#define QCA953X_RESET_DDR BIT(16) +#define QCA953X_RESET_USB_PHY_PLL_PWD_EXT BIT(15) +#define QCA953X_RESET_GE1_MAC BIT(13) +#define QCA953X_RESET_ETH_SWITCH_ANALOG BIT(12) +#define QCA953X_RESET_USB_PHY_ANALOG BIT(11) +#define QCA953X_RESET_GE0_MAC BIT(9) +#define QCA953X_RESET_ETH_SWITCH BIT(8) +#define QCA953X_RESET_PCIE_PHY BIT(7) +#define QCA953X_RESET_PCIE BIT(6) +#define QCA953X_RESET_USB_HOST BIT(5) +#define QCA953X_RESET_USB_PHY BIT(4) +#define QCA953X_RESET_USBSUS_OVERRIDE BIT(3) -#define QCA955X_RESET_HOST BIT(31) -#define QCA955X_RESET_SLIC BIT(30) -#define QCA955X_RESET_HDMA BIT(29) -#define QCA955X_RESET_EXTERNAL BIT(28) -#define QCA955X_RESET_RTC BIT(27) -#define QCA955X_RESET_PCIE_EP_INT BIT(26) -#define QCA955X_RESET_CHKSUM_ACC BIT(25) -#define QCA955X_RESET_FULL_CHIP BIT(24) -#define QCA955X_RESET_GE1_MDIO BIT(23) -#define QCA955X_RESET_GE0_MDIO BIT(22) -#define QCA955X_RESET_CPU_NMI BIT(21) -#define QCA955X_RESET_CPU_COLD BIT(20) -#define QCA955X_RESET_HOST_RESET_INT BIT(19) -#define QCA955X_RESET_PCIE_EP BIT(18) -#define QCA955X_RESET_UART1 BIT(17) -#define QCA955X_RESET_DDR BIT(16) -#define QCA955X_RESET_USB_PHY_PLL_PWD_EXT BIT(15) -#define QCA955X_RESET_NANDF BIT(14) -#define QCA955X_RESET_GE1_MAC BIT(13) -#define QCA955X_RESET_SGMII_ANALOG BIT(12) -#define QCA955X_RESET_USB_PHY_ANALOG BIT(11) -#define QCA955X_RESET_HOST_DMA_INT BIT(10) -#define QCA955X_RESET_GE0_MAC BIT(9) -#define QCA955X_RESET_SGMII BIT(8) -#define QCA955X_RESET_PCIE_PHY BIT(7) -#define QCA955X_RESET_PCIE BIT(6) -#define QCA955X_RESET_USB_HOST BIT(5) -#define QCA955X_RESET_USB_PHY BIT(4) -#define QCA955X_RESET_USBSUS_OVERRIDE BIT(3) -#define QCA955X_RESET_LUT BIT(2) -#define QCA955X_RESET_MBOX BIT(1) -#define QCA955X_RESET_I2S BIT(0) +#define QCA955X_RESET_HOST BIT(31) +#define QCA955X_RESET_SLIC BIT(30) +#define QCA955X_RESET_HDMA BIT(29) +#define QCA955X_RESET_EXTERNAL BIT(28) +#define QCA955X_RESET_RTC BIT(27) +#define QCA955X_RESET_PCIE_EP_INT BIT(26) +#define QCA955X_RESET_CHKSUM_ACC BIT(25) +#define QCA955X_RESET_FULL_CHIP BIT(24) +#define QCA955X_RESET_GE1_MDIO BIT(23) +#define QCA955X_RESET_GE0_MDIO BIT(22) +#define QCA955X_RESET_CPU_NMI BIT(21) +#define QCA955X_RESET_CPU_COLD BIT(20) +#define QCA955X_RESET_HOST_RESET_INT BIT(19) +#define QCA955X_RESET_PCIE_EP BIT(18) +#define QCA955X_RESET_UART1 BIT(17) +#define QCA955X_RESET_DDR BIT(16) +#define QCA955X_RESET_USB_PHY_PLL_PWD_EXT BIT(15) +#define QCA955X_RESET_NANDF BIT(14) +#define QCA955X_RESET_GE1_MAC BIT(13) +#define QCA955X_RESET_SGMII_ANALOG BIT(12) +#define QCA955X_RESET_USB_PHY_ANALOG BIT(11) +#define QCA955X_RESET_HOST_DMA_INT BIT(10) +#define QCA955X_RESET_GE0_MAC BIT(9) +#define QCA955X_RESET_SGMII BIT(8) +#define QCA955X_RESET_PCIE_PHY BIT(7) +#define QCA955X_RESET_PCIE BIT(6) +#define QCA955X_RESET_USB_HOST BIT(5) +#define QCA955X_RESET_USB_PHY BIT(4) +#define QCA955X_RESET_USBSUS_OVERRIDE BIT(3) +#define QCA955X_RESET_LUT BIT(2) +#define QCA955X_RESET_MBOX BIT(1) +#define QCA955X_RESET_I2S BIT(0) -#define AR933X_BOOTSTRAP_MDIO_GPIO_EN BIT(18) -#define AR933X_BOOTSTRAP_DDR2 BIT(13) -#define AR933X_BOOTSTRAP_EEPBUSY BIT(4) -#define AR933X_BOOTSTRAP_REF_CLK_40 BIT(0) +#define AR933X_BOOTSTRAP_MDIO_GPIO_EN BIT(18) +#define AR933X_BOOTSTRAP_DDR2 BIT(13) +#define AR933X_BOOTSTRAP_EEPBUSY BIT(4) +#define AR933X_BOOTSTRAP_REF_CLK_40 BIT(0) -#define AR934X_BOOTSTRAP_SW_OPTION8 BIT(23) -#define AR934X_BOOTSTRAP_SW_OPTION7 BIT(22) -#define AR934X_BOOTSTRAP_SW_OPTION6 BIT(21) -#define AR934X_BOOTSTRAP_SW_OPTION5 BIT(20) -#define AR934X_BOOTSTRAP_SW_OPTION4 BIT(19) -#define AR934X_BOOTSTRAP_SW_OPTION3 BIT(18) -#define AR934X_BOOTSTRAP_SW_OPTION2 BIT(17) -#define AR934X_BOOTSTRAP_SW_OPTION1 BIT(16) -#define AR934X_BOOTSTRAP_USB_MODE_DEVICE BIT(7) -#define AR934X_BOOTSTRAP_PCIE_RC BIT(6) -#define AR934X_BOOTSTRAP_EJTAG_MODE BIT(5) -#define AR934X_BOOTSTRAP_REF_CLK_40 BIT(4) -#define AR934X_BOOTSTRAP_BOOT_FROM_SPI BIT(2) -#define AR934X_BOOTSTRAP_SDRAM_DISABLED BIT(1) -#define AR934X_BOOTSTRAP_DDR1 BIT(0) +#define AR934X_BOOTSTRAP_SW_OPTION8 BIT(23) +#define AR934X_BOOTSTRAP_SW_OPTION7 BIT(22) +#define AR934X_BOOTSTRAP_SW_OPTION6 BIT(21) +#define AR934X_BOOTSTRAP_SW_OPTION5 BIT(20) +#define AR934X_BOOTSTRAP_SW_OPTION4 BIT(19) +#define AR934X_BOOTSTRAP_SW_OPTION3 BIT(18) +#define AR934X_BOOTSTRAP_SW_OPTION2 BIT(17) +#define AR934X_BOOTSTRAP_SW_OPTION1 BIT(16) +#define AR934X_BOOTSTRAP_USB_MODE_DEVICE BIT(7) +#define AR934X_BOOTSTRAP_PCIE_RC BIT(6) +#define AR934X_BOOTSTRAP_EJTAG_MODE BIT(5) +#define AR934X_BOOTSTRAP_REF_CLK_40 BIT(4) +#define AR934X_BOOTSTRAP_BOOT_FROM_SPI BIT(2) +#define AR934X_BOOTSTRAP_SDRAM_DISABLED BIT(1) +#define AR934X_BOOTSTRAP_DDR1 BIT(0) -#define QCA953X_BOOTSTRAP_SW_OPTION2 BIT(12) -#define QCA953X_BOOTSTRAP_SW_OPTION1 BIT(11) -#define QCA953X_BOOTSTRAP_EJTAG_MODE BIT(5) -#define QCA953X_BOOTSTRAP_REF_CLK_40 BIT(4) -#define QCA953X_BOOTSTRAP_SDRAM_DISABLED BIT(1) -#define QCA953X_BOOTSTRAP_DDR1 BIT(0) +#define QCA953X_BOOTSTRAP_SW_OPTION2 BIT(12) +#define QCA953X_BOOTSTRAP_SW_OPTION1 BIT(11) +#define QCA953X_BOOTSTRAP_EJTAG_MODE BIT(5) +#define QCA953X_BOOTSTRAP_REF_CLK_40 BIT(4) +#define QCA953X_BOOTSTRAP_SDRAM_DISABLED BIT(1) +#define QCA953X_BOOTSTRAP_DDR1 BIT(0) -#define QCA955X_BOOTSTRAP_REF_CLK_40 BIT(4) +#define QCA955X_BOOTSTRAP_REF_CLK_40 BIT(4) -#define QCA956X_BOOTSTRAP_REF_CLK_40 BIT(2) +#define QCA956X_BOOTSTRAP_REF_CLK_40 BIT(2) -#define AR934X_PCIE_WMAC_INT_WMAC_MISC BIT(0) -#define AR934X_PCIE_WMAC_INT_WMAC_TX BIT(1) -#define AR934X_PCIE_WMAC_INT_WMAC_RXLP BIT(2) -#define AR934X_PCIE_WMAC_INT_WMAC_RXHP BIT(3) -#define AR934X_PCIE_WMAC_INT_PCIE_RC BIT(4) -#define AR934X_PCIE_WMAC_INT_PCIE_RC0 BIT(5) -#define AR934X_PCIE_WMAC_INT_PCIE_RC1 BIT(6) -#define AR934X_PCIE_WMAC_INT_PCIE_RC2 BIT(7) -#define AR934X_PCIE_WMAC_INT_PCIE_RC3 BIT(8) +#define AR934X_PCIE_WMAC_INT_WMAC_MISC BIT(0) +#define AR934X_PCIE_WMAC_INT_WMAC_TX BIT(1) +#define AR934X_PCIE_WMAC_INT_WMAC_RXLP BIT(2) +#define AR934X_PCIE_WMAC_INT_WMAC_RXHP BIT(3) +#define AR934X_PCIE_WMAC_INT_PCIE_RC BIT(4) +#define AR934X_PCIE_WMAC_INT_PCIE_RC0 BIT(5) +#define AR934X_PCIE_WMAC_INT_PCIE_RC1 BIT(6) +#define AR934X_PCIE_WMAC_INT_PCIE_RC2 BIT(7) +#define AR934X_PCIE_WMAC_INT_PCIE_RC3 BIT(8) #define AR934X_PCIE_WMAC_INT_WMAC_ALL \ (AR934X_PCIE_WMAC_INT_WMAC_MISC | AR934X_PCIE_WMAC_INT_WMAC_TX | \ AR934X_PCIE_WMAC_INT_WMAC_RXLP | AR934X_PCIE_WMAC_INT_WMAC_RXHP) @@ -728,15 +763,15 @@ AR934X_PCIE_WMAC_INT_PCIE_RC1 | AR934X_PCIE_WMAC_INT_PCIE_RC2 | \ AR934X_PCIE_WMAC_INT_PCIE_RC3) -#define QCA953X_PCIE_WMAC_INT_WMAC_MISC BIT(0) -#define QCA953X_PCIE_WMAC_INT_WMAC_TX BIT(1) -#define QCA953X_PCIE_WMAC_INT_WMAC_RXLP BIT(2) -#define QCA953X_PCIE_WMAC_INT_WMAC_RXHP BIT(3) -#define QCA953X_PCIE_WMAC_INT_PCIE_RC BIT(4) -#define QCA953X_PCIE_WMAC_INT_PCIE_RC0 BIT(5) -#define QCA953X_PCIE_WMAC_INT_PCIE_RC1 BIT(6) -#define QCA953X_PCIE_WMAC_INT_PCIE_RC2 BIT(7) -#define QCA953X_PCIE_WMAC_INT_PCIE_RC3 BIT(8) +#define QCA953X_PCIE_WMAC_INT_WMAC_MISC BIT(0) +#define QCA953X_PCIE_WMAC_INT_WMAC_TX BIT(1) +#define QCA953X_PCIE_WMAC_INT_WMAC_RXLP BIT(2) +#define QCA953X_PCIE_WMAC_INT_WMAC_RXHP BIT(3) +#define QCA953X_PCIE_WMAC_INT_PCIE_RC BIT(4) +#define QCA953X_PCIE_WMAC_INT_PCIE_RC0 BIT(5) +#define QCA953X_PCIE_WMAC_INT_PCIE_RC1 BIT(6) +#define QCA953X_PCIE_WMAC_INT_PCIE_RC2 BIT(7) +#define QCA953X_PCIE_WMAC_INT_PCIE_RC3 BIT(8) #define QCA953X_PCIE_WMAC_INT_WMAC_ALL \ (QCA953X_PCIE_WMAC_INT_WMAC_MISC | QCA953X_PCIE_WMAC_INT_WMAC_TX | \ QCA953X_PCIE_WMAC_INT_WMAC_RXLP | QCA953X_PCIE_WMAC_INT_WMAC_RXHP) @@ -746,22 +781,22 @@ QCA953X_PCIE_WMAC_INT_PCIE_RC1 | QCA953X_PCIE_WMAC_INT_PCIE_RC2 | \ QCA953X_PCIE_WMAC_INT_PCIE_RC3) -#define QCA955X_EXT_INT_WMAC_MISC BIT(0) -#define QCA955X_EXT_INT_WMAC_TX BIT(1) -#define QCA955X_EXT_INT_WMAC_RXLP BIT(2) -#define QCA955X_EXT_INT_WMAC_RXHP BIT(3) -#define QCA955X_EXT_INT_PCIE_RC1 BIT(4) -#define QCA955X_EXT_INT_PCIE_RC1_INT0 BIT(5) -#define QCA955X_EXT_INT_PCIE_RC1_INT1 BIT(6) -#define QCA955X_EXT_INT_PCIE_RC1_INT2 BIT(7) -#define QCA955X_EXT_INT_PCIE_RC1_INT3 BIT(8) -#define QCA955X_EXT_INT_PCIE_RC2 BIT(12) -#define QCA955X_EXT_INT_PCIE_RC2_INT0 BIT(13) -#define QCA955X_EXT_INT_PCIE_RC2_INT1 BIT(14) -#define QCA955X_EXT_INT_PCIE_RC2_INT2 BIT(15) -#define QCA955X_EXT_INT_PCIE_RC2_INT3 BIT(16) -#define QCA955X_EXT_INT_USB1 BIT(24) -#define QCA955X_EXT_INT_USB2 BIT(28) +#define QCA955X_EXT_INT_WMAC_MISC BIT(0) +#define QCA955X_EXT_INT_WMAC_TX BIT(1) +#define QCA955X_EXT_INT_WMAC_RXLP BIT(2) +#define QCA955X_EXT_INT_WMAC_RXHP BIT(3) +#define QCA955X_EXT_INT_PCIE_RC1 BIT(4) +#define QCA955X_EXT_INT_PCIE_RC1_INT0 BIT(5) +#define QCA955X_EXT_INT_PCIE_RC1_INT1 BIT(6) +#define QCA955X_EXT_INT_PCIE_RC1_INT2 BIT(7) +#define QCA955X_EXT_INT_PCIE_RC1_INT3 BIT(8) +#define QCA955X_EXT_INT_PCIE_RC2 BIT(12) +#define QCA955X_EXT_INT_PCIE_RC2_INT0 BIT(13) +#define QCA955X_EXT_INT_PCIE_RC2_INT1 BIT(14) +#define QCA955X_EXT_INT_PCIE_RC2_INT2 BIT(15) +#define QCA955X_EXT_INT_PCIE_RC2_INT3 BIT(16) +#define QCA955X_EXT_INT_USB1 BIT(24) +#define QCA955X_EXT_INT_USB2 BIT(28) #define QCA955X_EXT_INT_WMAC_ALL \ (QCA955X_EXT_INT_WMAC_MISC | QCA955X_EXT_INT_WMAC_TX | \ @@ -777,22 +812,22 @@ QCA955X_EXT_INT_PCIE_RC2_INT1 | QCA955X_EXT_INT_PCIE_RC2_INT2 | \ QCA955X_EXT_INT_PCIE_RC2_INT3) -#define QCA956X_EXT_INT_WMAC_MISC BIT(0) -#define QCA956X_EXT_INT_WMAC_TX BIT(1) -#define QCA956X_EXT_INT_WMAC_RXLP BIT(2) -#define QCA956X_EXT_INT_WMAC_RXHP BIT(3) -#define QCA956X_EXT_INT_PCIE_RC1 BIT(4) -#define QCA956X_EXT_INT_PCIE_RC1_INT0 BIT(5) -#define QCA956X_EXT_INT_PCIE_RC1_INT1 BIT(6) -#define QCA956X_EXT_INT_PCIE_RC1_INT2 BIT(7) -#define QCA956X_EXT_INT_PCIE_RC1_INT3 BIT(8) -#define QCA956X_EXT_INT_PCIE_RC2 BIT(12) -#define QCA956X_EXT_INT_PCIE_RC2_INT0 BIT(13) -#define QCA956X_EXT_INT_PCIE_RC2_INT1 BIT(14) -#define QCA956X_EXT_INT_PCIE_RC2_INT2 BIT(15) -#define QCA956X_EXT_INT_PCIE_RC2_INT3 BIT(16) -#define QCA956X_EXT_INT_USB1 BIT(24) -#define QCA956X_EXT_INT_USB2 BIT(28) +#define QCA956X_EXT_INT_WMAC_MISC BIT(0) +#define QCA956X_EXT_INT_WMAC_TX BIT(1) +#define QCA956X_EXT_INT_WMAC_RXLP BIT(2) +#define QCA956X_EXT_INT_WMAC_RXHP BIT(3) +#define QCA956X_EXT_INT_PCIE_RC1 BIT(4) +#define QCA956X_EXT_INT_PCIE_RC1_INT0 BIT(5) +#define QCA956X_EXT_INT_PCIE_RC1_INT1 BIT(6) +#define QCA956X_EXT_INT_PCIE_RC1_INT2 BIT(7) +#define QCA956X_EXT_INT_PCIE_RC1_INT3 BIT(8) +#define QCA956X_EXT_INT_PCIE_RC2 BIT(12) +#define QCA956X_EXT_INT_PCIE_RC2_INT0 BIT(13) +#define QCA956X_EXT_INT_PCIE_RC2_INT1 BIT(14) +#define QCA956X_EXT_INT_PCIE_RC2_INT2 BIT(15) +#define QCA956X_EXT_INT_PCIE_RC2_INT3 BIT(16) +#define QCA956X_EXT_INT_USB1 BIT(24) +#define QCA956X_EXT_INT_USB2 BIT(28) #define QCA956X_EXT_INT_WMAC_ALL \ (QCA956X_EXT_INT_WMAC_MISC | QCA956X_EXT_INT_WMAC_TX | \ @@ -808,377 +843,377 @@ QCA956X_EXT_INT_PCIE_RC2_INT1 | QCA956X_EXT_INT_PCIE_RC2_INT2 | \ QCA956X_EXT_INT_PCIE_RC2_INT3) -#define REV_ID_MAJOR_MASK 0xfff0 -#define REV_ID_MAJOR_AR71XX 0x00a0 -#define REV_ID_MAJOR_AR913X 0x00b0 -#define REV_ID_MAJOR_AR7240 0x00c0 -#define REV_ID_MAJOR_AR7241 0x0100 -#define REV_ID_MAJOR_AR7242 0x1100 -#define REV_ID_MAJOR_AR9330 0x0110 -#define REV_ID_MAJOR_AR9331 0x1110 -#define REV_ID_MAJOR_AR9341 0x0120 -#define REV_ID_MAJOR_AR9342 0x1120 -#define REV_ID_MAJOR_AR9344 0x2120 -#define REV_ID_MAJOR_QCA9533 0x0140 -#define REV_ID_MAJOR_QCA9533_V2 0x0160 -#define REV_ID_MAJOR_QCA9556 0x0130 -#define REV_ID_MAJOR_QCA9558 0x1130 -#define REV_ID_MAJOR_TP9343 0x0150 -#define REV_ID_MAJOR_QCA9561 0x1150 +#define REV_ID_MAJOR_MASK 0xfff0 +#define REV_ID_MAJOR_AR71XX 0x00a0 +#define REV_ID_MAJOR_AR913X 0x00b0 +#define REV_ID_MAJOR_AR7240 0x00c0 +#define REV_ID_MAJOR_AR7241 0x0100 +#define REV_ID_MAJOR_AR7242 0x1100 +#define REV_ID_MAJOR_AR9330 0x0110 +#define REV_ID_MAJOR_AR9331 0x1110 +#define REV_ID_MAJOR_AR9341 0x0120 +#define REV_ID_MAJOR_AR9342 0x1120 +#define REV_ID_MAJOR_AR9344 0x2120 +#define REV_ID_MAJOR_QCA9533 0x0140 +#define REV_ID_MAJOR_QCA9533_V2 0x0160 +#define REV_ID_MAJOR_QCA9556 0x0130 +#define REV_ID_MAJOR_QCA9558 0x1130 +#define REV_ID_MAJOR_TP9343 0x0150 +#define REV_ID_MAJOR_QCA9561 0x1150 -#define AR71XX_REV_ID_MINOR_MASK 0x3 -#define AR71XX_REV_ID_MINOR_AR7130 0x0 -#define AR71XX_REV_ID_MINOR_AR7141 0x1 -#define AR71XX_REV_ID_MINOR_AR7161 0x2 -#define AR913X_REV_ID_MINOR_AR9130 0x0 -#define AR913X_REV_ID_MINOR_AR9132 0x1 +#define AR71XX_REV_ID_MINOR_MASK 0x3 +#define AR71XX_REV_ID_MINOR_AR7130 0x0 +#define AR71XX_REV_ID_MINOR_AR7141 0x1 +#define AR71XX_REV_ID_MINOR_AR7161 0x2 +#define AR913X_REV_ID_MINOR_AR9130 0x0 +#define AR913X_REV_ID_MINOR_AR9132 0x1 -#define AR71XX_REV_ID_REVISION_MASK 0x3 -#define AR71XX_REV_ID_REVISION_SHIFT 2 -#define AR71XX_REV_ID_REVISION2_MASK 0xf +#define AR71XX_REV_ID_REVISION_MASK 0x3 +#define AR71XX_REV_ID_REVISION_SHIFT 2 +#define AR71XX_REV_ID_REVISION2_MASK 0xf /* * RTC block */ -#define AR933X_RTC_REG_RESET 0x40 -#define AR933X_RTC_REG_STATUS 0x44 -#define AR933X_RTC_REG_DERIVED 0x48 -#define AR933X_RTC_REG_FORCE_WAKE 0x4c -#define AR933X_RTC_REG_INT_CAUSE 0x50 -#define AR933X_RTC_REG_CAUSE_CLR 0x50 -#define AR933X_RTC_REG_INT_ENABLE 0x54 -#define AR933X_RTC_REG_INT_MASKE 0x58 +#define AR933X_RTC_REG_RESET 0x40 +#define AR933X_RTC_REG_STATUS 0x44 +#define AR933X_RTC_REG_DERIVED 0x48 +#define AR933X_RTC_REG_FORCE_WAKE 0x4c +#define AR933X_RTC_REG_INT_CAUSE 0x50 +#define AR933X_RTC_REG_CAUSE_CLR 0x50 +#define AR933X_RTC_REG_INT_ENABLE 0x54 +#define AR933X_RTC_REG_INT_MASKE 0x58 -#define QCA953X_RTC_REG_SYNC_RESET 0x40 -#define QCA953X_RTC_REG_SYNC_STATUS 0x44 +#define QCA953X_RTC_REG_SYNC_RESET 0x40 +#define QCA953X_RTC_REG_SYNC_STATUS 0x44 /* * SPI block */ -#define AR71XX_SPI_REG_FS 0x00 -#define AR71XX_SPI_REG_CTRL 0x04 -#define AR71XX_SPI_REG_IOC 0x08 -#define AR71XX_SPI_REG_RDS 0x0c +#define AR71XX_SPI_REG_FS 0x00 +#define AR71XX_SPI_REG_CTRL 0x04 +#define AR71XX_SPI_REG_IOC 0x08 +#define AR71XX_SPI_REG_RDS 0x0c -#define AR71XX_SPI_FS_GPIO BIT(0) +#define AR71XX_SPI_FS_GPIO BIT(0) -#define AR71XX_SPI_CTRL_RD BIT(6) -#define AR71XX_SPI_CTRL_DIV_MASK 0x3f +#define AR71XX_SPI_CTRL_RD BIT(6) +#define AR71XX_SPI_CTRL_DIV_MASK 0x3f -#define AR71XX_SPI_IOC_DO BIT(0) -#define AR71XX_SPI_IOC_CLK BIT(8) -#define AR71XX_SPI_IOC_CS(n) BIT(16 + (n)) -#define AR71XX_SPI_IOC_CS0 AR71XX_SPI_IOC_CS(0) -#define AR71XX_SPI_IOC_CS1 AR71XX_SPI_IOC_CS(1) -#define AR71XX_SPI_IOC_CS2 AR71XX_SPI_IOC_CS(2) +#define AR71XX_SPI_IOC_DO BIT(0) +#define AR71XX_SPI_IOC_CLK BIT(8) +#define AR71XX_SPI_IOC_CS(n) BIT(16 + (n)) +#define AR71XX_SPI_IOC_CS0 AR71XX_SPI_IOC_CS(0) +#define AR71XX_SPI_IOC_CS1 AR71XX_SPI_IOC_CS(1) +#define AR71XX_SPI_IOC_CS2 AR71XX_SPI_IOC_CS(2) #define AR71XX_SPI_IOC_CS_ALL \ (AR71XX_SPI_IOC_CS0 | AR71XX_SPI_IOC_CS1 | AR71XX_SPI_IOC_CS2) /* * GPIO block */ -#define AR71XX_GPIO_REG_OE 0x00 -#define AR71XX_GPIO_REG_IN 0x04 -#define AR71XX_GPIO_REG_OUT 0x08 -#define AR71XX_GPIO_REG_SET 0x0c -#define AR71XX_GPIO_REG_CLEAR 0x10 -#define AR71XX_GPIO_REG_INT_MODE 0x14 -#define AR71XX_GPIO_REG_INT_TYPE 0x18 -#define AR71XX_GPIO_REG_INT_POLARITY 0x1c -#define AR71XX_GPIO_REG_INT_PENDING 0x20 -#define AR71XX_GPIO_REG_INT_ENABLE 0x24 -#define AR71XX_GPIO_REG_FUNC 0x28 -#define AR933X_GPIO_REG_FUNC 0x30 +#define AR71XX_GPIO_REG_OE 0x00 +#define AR71XX_GPIO_REG_IN 0x04 +#define AR71XX_GPIO_REG_OUT 0x08 +#define AR71XX_GPIO_REG_SET 0x0c +#define AR71XX_GPIO_REG_CLEAR 0x10 +#define AR71XX_GPIO_REG_INT_MODE 0x14 +#define AR71XX_GPIO_REG_INT_TYPE 0x18 +#define AR71XX_GPIO_REG_INT_POLARITY 0x1c +#define AR71XX_GPIO_REG_INT_PENDING 0x20 +#define AR71XX_GPIO_REG_INT_ENABLE 0x24 +#define AR71XX_GPIO_REG_FUNC 0x28 +#define AR933X_GPIO_REG_FUNC 0x30 -#define AR934X_GPIO_REG_OUT_FUNC0 0x2c -#define AR934X_GPIO_REG_OUT_FUNC1 0x30 -#define AR934X_GPIO_REG_OUT_FUNC2 0x34 -#define AR934X_GPIO_REG_OUT_FUNC3 0x38 -#define AR934X_GPIO_REG_OUT_FUNC4 0x3c -#define AR934X_GPIO_REG_OUT_FUNC5 0x40 -#define AR934X_GPIO_REG_FUNC 0x6c +#define AR934X_GPIO_REG_OUT_FUNC0 0x2c +#define AR934X_GPIO_REG_OUT_FUNC1 0x30 +#define AR934X_GPIO_REG_OUT_FUNC2 0x34 +#define AR934X_GPIO_REG_OUT_FUNC3 0x38 +#define AR934X_GPIO_REG_OUT_FUNC4 0x3c +#define AR934X_GPIO_REG_OUT_FUNC5 0x40 +#define AR934X_GPIO_REG_FUNC 0x6c -#define QCA953X_GPIO_REG_OUT_FUNC0 0x2c -#define QCA953X_GPIO_REG_OUT_FUNC1 0x30 -#define QCA953X_GPIO_REG_OUT_FUNC2 0x34 -#define QCA953X_GPIO_REG_OUT_FUNC3 0x38 -#define QCA953X_GPIO_REG_OUT_FUNC4 0x3c -#define QCA953X_GPIO_REG_IN_ENABLE0 0x44 -#define QCA953X_GPIO_REG_FUNC 0x6c +#define QCA953X_GPIO_REG_OUT_FUNC0 0x2c +#define QCA953X_GPIO_REG_OUT_FUNC1 0x30 +#define QCA953X_GPIO_REG_OUT_FUNC2 0x34 +#define QCA953X_GPIO_REG_OUT_FUNC3 0x38 +#define QCA953X_GPIO_REG_OUT_FUNC4 0x3c +#define QCA953X_GPIO_REG_IN_ENABLE0 0x44 +#define QCA953X_GPIO_REG_FUNC 0x6c -#define QCA955X_GPIO_REG_OUT_FUNC0 0x2c -#define QCA955X_GPIO_REG_OUT_FUNC1 0x30 -#define QCA955X_GPIO_REG_OUT_FUNC2 0x34 -#define QCA955X_GPIO_REG_OUT_FUNC3 0x38 -#define QCA955X_GPIO_REG_OUT_FUNC4 0x3c -#define QCA955X_GPIO_REG_OUT_FUNC5 0x40 -#define QCA955X_GPIO_REG_FUNC 0x6c +#define QCA955X_GPIO_REG_OUT_FUNC0 0x2c +#define QCA955X_GPIO_REG_OUT_FUNC1 0x30 +#define QCA955X_GPIO_REG_OUT_FUNC2 0x34 +#define QCA955X_GPIO_REG_OUT_FUNC3 0x38 +#define QCA955X_GPIO_REG_OUT_FUNC4 0x3c +#define QCA955X_GPIO_REG_OUT_FUNC5 0x40 +#define QCA955X_GPIO_REG_FUNC 0x6c -#define QCA956X_GPIO_REG_OUT_FUNC0 0x2c -#define QCA956X_GPIO_REG_OUT_FUNC1 0x30 -#define QCA956X_GPIO_REG_OUT_FUNC2 0x34 -#define QCA956X_GPIO_REG_OUT_FUNC3 0x38 -#define QCA956X_GPIO_REG_OUT_FUNC4 0x3c -#define QCA956X_GPIO_REG_OUT_FUNC5 0x40 -#define QCA956X_GPIO_REG_IN_ENABLE0 0x44 -#define QCA956X_GPIO_REG_IN_ENABLE3 0x50 -#define QCA956X_GPIO_REG_FUNC 0x6c +#define QCA956X_GPIO_REG_OUT_FUNC0 0x2c +#define QCA956X_GPIO_REG_OUT_FUNC1 0x30 +#define QCA956X_GPIO_REG_OUT_FUNC2 0x34 +#define QCA956X_GPIO_REG_OUT_FUNC3 0x38 +#define QCA956X_GPIO_REG_OUT_FUNC4 0x3c +#define QCA956X_GPIO_REG_OUT_FUNC5 0x40 +#define QCA956X_GPIO_REG_IN_ENABLE0 0x44 +#define QCA956X_GPIO_REG_IN_ENABLE3 0x50 +#define QCA956X_GPIO_REG_FUNC 0x6c -#define AR71XX_GPIO_FUNC_STEREO_EN BIT(17) -#define AR71XX_GPIO_FUNC_SLIC_EN BIT(16) -#define AR71XX_GPIO_FUNC_SPI_CS2_EN BIT(13) -#define AR71XX_GPIO_FUNC_SPI_CS1_EN BIT(12) -#define AR71XX_GPIO_FUNC_UART_EN BIT(8) -#define AR71XX_GPIO_FUNC_USB_OC_EN BIT(4) -#define AR71XX_GPIO_FUNC_USB_CLK_EN BIT(0) +#define AR71XX_GPIO_FUNC_STEREO_EN BIT(17) +#define AR71XX_GPIO_FUNC_SLIC_EN BIT(16) +#define AR71XX_GPIO_FUNC_SPI_CS2_EN BIT(13) +#define AR71XX_GPIO_FUNC_SPI_CS1_EN BIT(12) +#define AR71XX_GPIO_FUNC_UART_EN BIT(8) +#define AR71XX_GPIO_FUNC_USB_OC_EN BIT(4) +#define AR71XX_GPIO_FUNC_USB_CLK_EN BIT(0) -#define AR724X_GPIO_FUNC_GE0_MII_CLK_EN BIT(19) -#define AR724X_GPIO_FUNC_SPI_EN BIT(18) -#define AR724X_GPIO_FUNC_SPI_CS_EN2 BIT(14) -#define AR724X_GPIO_FUNC_SPI_CS_EN1 BIT(13) -#define AR724X_GPIO_FUNC_CLK_OBS5_EN BIT(12) -#define AR724X_GPIO_FUNC_CLK_OBS4_EN BIT(11) -#define AR724X_GPIO_FUNC_CLK_OBS3_EN BIT(10) -#define AR724X_GPIO_FUNC_CLK_OBS2_EN BIT(9) -#define AR724X_GPIO_FUNC_CLK_OBS1_EN BIT(8) -#define AR724X_GPIO_FUNC_ETH_SWITCH_LED4_EN BIT(7) -#define AR724X_GPIO_FUNC_ETH_SWITCH_LED3_EN BIT(6) -#define AR724X_GPIO_FUNC_ETH_SWITCH_LED2_EN BIT(5) -#define AR724X_GPIO_FUNC_ETH_SWITCH_LED1_EN BIT(4) -#define AR724X_GPIO_FUNC_ETH_SWITCH_LED0_EN BIT(3) -#define AR724X_GPIO_FUNC_UART_RTS_CTS_EN BIT(2) -#define AR724X_GPIO_FUNC_UART_EN BIT(1) -#define AR724X_GPIO_FUNC_JTAG_DISABLE BIT(0) +#define AR724X_GPIO_FUNC_GE0_MII_CLK_EN BIT(19) +#define AR724X_GPIO_FUNC_SPI_EN BIT(18) +#define AR724X_GPIO_FUNC_SPI_CS_EN2 BIT(14) +#define AR724X_GPIO_FUNC_SPI_CS_EN1 BIT(13) +#define AR724X_GPIO_FUNC_CLK_OBS5_EN BIT(12) +#define AR724X_GPIO_FUNC_CLK_OBS4_EN BIT(11) +#define AR724X_GPIO_FUNC_CLK_OBS3_EN BIT(10) +#define AR724X_GPIO_FUNC_CLK_OBS2_EN BIT(9) +#define AR724X_GPIO_FUNC_CLK_OBS1_EN BIT(8) +#define AR724X_GPIO_FUNC_ETH_SWITCH_LED4_EN BIT(7) +#define AR724X_GPIO_FUNC_ETH_SWITCH_LED3_EN BIT(6) +#define AR724X_GPIO_FUNC_ETH_SWITCH_LED2_EN BIT(5) +#define AR724X_GPIO_FUNC_ETH_SWITCH_LED1_EN BIT(4) +#define AR724X_GPIO_FUNC_ETH_SWITCH_LED0_EN BIT(3) +#define AR724X_GPIO_FUNC_UART_RTS_CTS_EN BIT(2) +#define AR724X_GPIO_FUNC_UART_EN BIT(1) +#define AR724X_GPIO_FUNC_JTAG_DISABLE BIT(0) -#define AR913X_GPIO_FUNC_WMAC_LED_EN BIT(22) -#define AR913X_GPIO_FUNC_EXP_PORT_CS_EN BIT(21) -#define AR913X_GPIO_FUNC_I2S_REFCLKEN BIT(20) -#define AR913X_GPIO_FUNC_I2S_MCKEN BIT(19) -#define AR913X_GPIO_FUNC_I2S1_EN BIT(18) -#define AR913X_GPIO_FUNC_I2S0_EN BIT(17) -#define AR913X_GPIO_FUNC_SLIC_EN BIT(16) -#define AR913X_GPIO_FUNC_UART_RTSCTS_EN BIT(9) -#define AR913X_GPIO_FUNC_UART_EN BIT(8) -#define AR913X_GPIO_FUNC_USB_CLK_EN BIT(4) +#define AR913X_GPIO_FUNC_WMAC_LED_EN BIT(22) +#define AR913X_GPIO_FUNC_EXP_PORT_CS_EN BIT(21) +#define AR913X_GPIO_FUNC_I2S_REFCLKEN BIT(20) +#define AR913X_GPIO_FUNC_I2S_MCKEN BIT(19) +#define AR913X_GPIO_FUNC_I2S1_EN BIT(18) +#define AR913X_GPIO_FUNC_I2S0_EN BIT(17) +#define AR913X_GPIO_FUNC_SLIC_EN BIT(16) +#define AR913X_GPIO_FUNC_UART_RTSCTS_EN BIT(9) +#define AR913X_GPIO_FUNC_UART_EN BIT(8) +#define AR913X_GPIO_FUNC_USB_CLK_EN BIT(4) -#define AR933X_GPIO(x) BIT(x) -#define AR933X_GPIO_FUNC_SPDIF2TCK BIT(31) -#define AR933X_GPIO_FUNC_SPDIF_EN BIT(30) -#define AR933X_GPIO_FUNC_I2SO_22_18_EN BIT(29) -#define AR933X_GPIO_FUNC_I2S_MCK_EN BIT(27) -#define AR933X_GPIO_FUNC_I2SO_EN BIT(26) -#define AR933X_GPIO_FUNC_ETH_SWITCH_LED_DUPL BIT(25) -#define AR933X_GPIO_FUNC_ETH_SWITCH_LED_COLL BIT(24) -#define AR933X_GPIO_FUNC_ETH_SWITCH_LED_ACT BIT(23) -#define AR933X_GPIO_FUNC_SPI_EN BIT(18) -#define AR933X_GPIO_FUNC_RES_TRUE BIT(15) -#define AR933X_GPIO_FUNC_SPI_CS_EN2 BIT(14) -#define AR933X_GPIO_FUNC_SPI_CS_EN1 BIT(13) -#define AR933X_GPIO_FUNC_XLNA_EN BIT(12) -#define AR933X_GPIO_FUNC_ETH_SWITCH_LED4_EN BIT(7) -#define AR933X_GPIO_FUNC_ETH_SWITCH_LED3_EN BIT(6) -#define AR933X_GPIO_FUNC_ETH_SWITCH_LED2_EN BIT(5) -#define AR933X_GPIO_FUNC_ETH_SWITCH_LED1_EN BIT(4) -#define AR933X_GPIO_FUNC_ETH_SWITCH_LED0_EN BIT(3) -#define AR933X_GPIO_FUNC_UART_RTS_CTS_EN BIT(2) -#define AR933X_GPIO_FUNC_UART_EN BIT(1) -#define AR933X_GPIO_FUNC_JTAG_DISABLE BIT(0) +#define AR933X_GPIO(x) BIT(x) +#define AR933X_GPIO_FUNC_SPDIF2TCK BIT(31) +#define AR933X_GPIO_FUNC_SPDIF_EN BIT(30) +#define AR933X_GPIO_FUNC_I2SO_22_18_EN BIT(29) +#define AR933X_GPIO_FUNC_I2S_MCK_EN BIT(27) +#define AR933X_GPIO_FUNC_I2SO_EN BIT(26) +#define AR933X_GPIO_FUNC_ETH_SWITCH_LED_DUPL BIT(25) +#define AR933X_GPIO_FUNC_ETH_SWITCH_LED_COLL BIT(24) +#define AR933X_GPIO_FUNC_ETH_SWITCH_LED_ACT BIT(23) +#define AR933X_GPIO_FUNC_SPI_EN BIT(18) +#define AR933X_GPIO_FUNC_RES_TRUE BIT(15) +#define AR933X_GPIO_FUNC_SPI_CS_EN2 BIT(14) +#define AR933X_GPIO_FUNC_SPI_CS_EN1 BIT(13) +#define AR933X_GPIO_FUNC_XLNA_EN BIT(12) +#define AR933X_GPIO_FUNC_ETH_SWITCH_LED4_EN BIT(7) +#define AR933X_GPIO_FUNC_ETH_SWITCH_LED3_EN BIT(6) +#define AR933X_GPIO_FUNC_ETH_SWITCH_LED2_EN BIT(5) +#define AR933X_GPIO_FUNC_ETH_SWITCH_LED1_EN BIT(4) +#define AR933X_GPIO_FUNC_ETH_SWITCH_LED0_EN BIT(3) +#define AR933X_GPIO_FUNC_UART_RTS_CTS_EN BIT(2) +#define AR933X_GPIO_FUNC_UART_EN BIT(1) +#define AR933X_GPIO_FUNC_JTAG_DISABLE BIT(0) -#define AR934X_GPIO_FUNC_CLK_OBS7_EN BIT(9) -#define AR934X_GPIO_FUNC_CLK_OBS6_EN BIT(8) -#define AR934X_GPIO_FUNC_CLK_OBS5_EN BIT(7) -#define AR934X_GPIO_FUNC_CLK_OBS4_EN BIT(6) -#define AR934X_GPIO_FUNC_CLK_OBS3_EN BIT(5) -#define AR934X_GPIO_FUNC_CLK_OBS2_EN BIT(4) -#define AR934X_GPIO_FUNC_CLK_OBS1_EN BIT(3) -#define AR934X_GPIO_FUNC_CLK_OBS0_EN BIT(2) -#define AR934X_GPIO_FUNC_JTAG_DISABLE BIT(1) +#define AR934X_GPIO_FUNC_CLK_OBS7_EN BIT(9) +#define AR934X_GPIO_FUNC_CLK_OBS6_EN BIT(8) +#define AR934X_GPIO_FUNC_CLK_OBS5_EN BIT(7) +#define AR934X_GPIO_FUNC_CLK_OBS4_EN BIT(6) +#define AR934X_GPIO_FUNC_CLK_OBS3_EN BIT(5) +#define AR934X_GPIO_FUNC_CLK_OBS2_EN BIT(4) +#define AR934X_GPIO_FUNC_CLK_OBS1_EN BIT(3) +#define AR934X_GPIO_FUNC_CLK_OBS0_EN BIT(2) +#define AR934X_GPIO_FUNC_JTAG_DISABLE BIT(1) -#define AR934X_GPIO_OUT_GPIO 0 -#define AR934X_GPIO_OUT_SPI_CS1 7 -#define AR934X_GPIO_OUT_LED_LINK0 41 -#define AR934X_GPIO_OUT_LED_LINK1 42 -#define AR934X_GPIO_OUT_LED_LINK2 43 -#define AR934X_GPIO_OUT_LED_LINK3 44 -#define AR934X_GPIO_OUT_LED_LINK4 45 -#define AR934X_GPIO_OUT_EXT_LNA0 46 -#define AR934X_GPIO_OUT_EXT_LNA1 47 +#define AR934X_GPIO_OUT_GPIO 0 +#define AR934X_GPIO_OUT_SPI_CS1 7 +#define AR934X_GPIO_OUT_LED_LINK0 41 +#define AR934X_GPIO_OUT_LED_LINK1 42 +#define AR934X_GPIO_OUT_LED_LINK2 43 +#define AR934X_GPIO_OUT_LED_LINK3 44 +#define AR934X_GPIO_OUT_LED_LINK4 45 +#define AR934X_GPIO_OUT_EXT_LNA0 46 +#define AR934X_GPIO_OUT_EXT_LNA1 47 -#define QCA953X_GPIO(x) BIT(x) -#define QCA953X_GPIO_MUX_MASK(x) (0xff << (x)) -#define QCA953X_GPIO_OUT_MUX_SPI_CS1 10 -#define QCA953X_GPIO_OUT_MUX_SPI_CS2 11 -#define QCA953X_GPIO_OUT_MUX_SPI_CS0 9 -#define QCA953X_GPIO_OUT_MUX_SPI_CLK 8 -#define QCA953X_GPIO_OUT_MUX_SPI_MOSI 12 -#define QCA953X_GPIO_OUT_MUX_UART0_SOUT 22 -#define QCA953X_GPIO_OUT_MUX_LED_LINK1 41 -#define QCA953X_GPIO_OUT_MUX_LED_LINK2 42 -#define QCA953X_GPIO_OUT_MUX_LED_LINK3 43 -#define QCA953X_GPIO_OUT_MUX_LED_LINK4 44 -#define QCA953X_GPIO_OUT_MUX_LED_LINK5 45 +#define QCA953X_GPIO(x) BIT(x) +#define QCA953X_GPIO_MUX_MASK(x) (0xff << (x)) +#define QCA953X_GPIO_OUT_MUX_SPI_CS1 10 +#define QCA953X_GPIO_OUT_MUX_SPI_CS2 11 +#define QCA953X_GPIO_OUT_MUX_SPI_CS0 9 +#define QCA953X_GPIO_OUT_MUX_SPI_CLK 8 +#define QCA953X_GPIO_OUT_MUX_SPI_MOSI 12 +#define QCA953X_GPIO_OUT_MUX_UART0_SOUT 22 +#define QCA953X_GPIO_OUT_MUX_LED_LINK1 41 +#define QCA953X_GPIO_OUT_MUX_LED_LINK2 42 +#define QCA953X_GPIO_OUT_MUX_LED_LINK3 43 +#define QCA953X_GPIO_OUT_MUX_LED_LINK4 44 +#define QCA953X_GPIO_OUT_MUX_LED_LINK5 45 -#define QCA953X_GPIO_IN_MUX_UART0_SIN 9 -#define QCA953X_GPIO_IN_MUX_SPI_DATA_IN 8 +#define QCA953X_GPIO_IN_MUX_UART0_SIN 9 +#define QCA953X_GPIO_IN_MUX_SPI_DATA_IN 8 -#define QCA956X_GPIO_OUT_MUX_GE0_MDO 32 -#define QCA956X_GPIO_OUT_MUX_GE0_MDC 33 +#define QCA956X_GPIO_OUT_MUX_GE0_MDO 32 +#define QCA956X_GPIO_OUT_MUX_GE0_MDC 33 -#define AR71XX_GPIO_COUNT 16 -#define AR7240_GPIO_COUNT 18 -#define AR7241_GPIO_COUNT 20 -#define AR913X_GPIO_COUNT 22 -#define AR933X_GPIO_COUNT 30 -#define AR934X_GPIO_COUNT 23 -#define QCA953X_GPIO_COUNT 18 -#define QCA955X_GPIO_COUNT 24 -#define QCA956X_GPIO_COUNT 23 +#define AR71XX_GPIO_COUNT 16 +#define AR7240_GPIO_COUNT 18 +#define AR7241_GPIO_COUNT 20 +#define AR913X_GPIO_COUNT 22 +#define AR933X_GPIO_COUNT 30 +#define AR934X_GPIO_COUNT 23 +#define QCA953X_GPIO_COUNT 18 +#define QCA955X_GPIO_COUNT 24 +#define QCA956X_GPIO_COUNT 23 /* * SRIF block */ -#define AR933X_SRIF_DDR_DPLL1_REG 0x240 -#define AR933X_SRIF_DDR_DPLL2_REG 0x244 -#define AR933X_SRIF_DDR_DPLL3_REG 0x248 -#define AR933X_SRIF_DDR_DPLL4_REG 0x24c +#define AR933X_SRIF_DDR_DPLL1_REG 0x240 +#define AR933X_SRIF_DDR_DPLL2_REG 0x244 +#define AR933X_SRIF_DDR_DPLL3_REG 0x248 +#define AR933X_SRIF_DDR_DPLL4_REG 0x24c -#define AR934X_SRIF_CPU_DPLL1_REG 0x1c0 -#define AR934X_SRIF_CPU_DPLL2_REG 0x1c4 -#define AR934X_SRIF_CPU_DPLL3_REG 0x1c8 +#define AR934X_SRIF_CPU_DPLL1_REG 0x1c0 +#define AR934X_SRIF_CPU_DPLL2_REG 0x1c4 +#define AR934X_SRIF_CPU_DPLL3_REG 0x1c8 -#define AR934X_SRIF_DDR_DPLL1_REG 0x240 -#define AR934X_SRIF_DDR_DPLL2_REG 0x244 -#define AR934X_SRIF_DDR_DPLL3_REG 0x248 +#define AR934X_SRIF_DDR_DPLL1_REG 0x240 +#define AR934X_SRIF_DDR_DPLL2_REG 0x244 +#define AR934X_SRIF_DDR_DPLL3_REG 0x248 -#define AR934X_SRIF_DPLL1_REFDIV_SHIFT 27 -#define AR934X_SRIF_DPLL1_REFDIV_MASK 0x1f -#define AR934X_SRIF_DPLL1_NINT_SHIFT 18 -#define AR934X_SRIF_DPLL1_NINT_MASK 0x1ff -#define AR934X_SRIF_DPLL1_NFRAC_MASK 0x0003ffff +#define AR934X_SRIF_DPLL1_REFDIV_SHIFT 27 +#define AR934X_SRIF_DPLL1_REFDIV_MASK 0x1f +#define AR934X_SRIF_DPLL1_NINT_SHIFT 18 +#define AR934X_SRIF_DPLL1_NINT_MASK 0x1ff +#define AR934X_SRIF_DPLL1_NFRAC_MASK 0x0003ffff -#define AR934X_SRIF_DPLL2_LOCAL_PLL BIT(30) -#define AR934X_SRIF_DPLL2_OUTDIV_SHIFT 13 -#define AR934X_SRIF_DPLL2_OUTDIV_MASK 0x7 +#define AR934X_SRIF_DPLL2_LOCAL_PLL BIT(30) +#define AR934X_SRIF_DPLL2_OUTDIV_SHIFT 13 +#define AR934X_SRIF_DPLL2_OUTDIV_MASK 0x7 -#define QCA953X_SRIF_BB_DPLL1_REG 0x180 -#define QCA953X_SRIF_BB_DPLL2_REG 0x184 -#define QCA953X_SRIF_BB_DPLL3_REG 0x188 +#define QCA953X_SRIF_BB_DPLL1_REG 0x180 +#define QCA953X_SRIF_BB_DPLL2_REG 0x184 +#define QCA953X_SRIF_BB_DPLL3_REG 0x188 -#define QCA953X_SRIF_CPU_DPLL1_REG 0x1c0 -#define QCA953X_SRIF_CPU_DPLL2_REG 0x1c4 -#define QCA953X_SRIF_CPU_DPLL3_REG 0x1c8 +#define QCA953X_SRIF_CPU_DPLL1_REG 0x1c0 +#define QCA953X_SRIF_CPU_DPLL2_REG 0x1c4 +#define QCA953X_SRIF_CPU_DPLL3_REG 0x1c8 -#define QCA953X_SRIF_DDR_DPLL1_REG 0x240 -#define QCA953X_SRIF_DDR_DPLL2_REG 0x244 -#define QCA953X_SRIF_DDR_DPLL3_REG 0x248 +#define QCA953X_SRIF_DDR_DPLL1_REG 0x240 +#define QCA953X_SRIF_DDR_DPLL2_REG 0x244 +#define QCA953X_SRIF_DDR_DPLL3_REG 0x248 -#define QCA953X_SRIF_PCIE_DPLL1_REG 0xc00 -#define QCA953X_SRIF_PCIE_DPLL2_REG 0xc04 -#define QCA953X_SRIF_PCIE_DPLL3_REG 0xc08 +#define QCA953X_SRIF_PCIE_DPLL1_REG 0xc00 +#define QCA953X_SRIF_PCIE_DPLL2_REG 0xc04 +#define QCA953X_SRIF_PCIE_DPLL3_REG 0xc08 -#define QCA953X_SRIF_PMU1_REG 0xc40 -#define QCA953X_SRIF_PMU2_REG 0xc44 +#define QCA953X_SRIF_PMU1_REG 0xc40 +#define QCA953X_SRIF_PMU2_REG 0xc44 -#define QCA953X_SRIF_DPLL1_REFDIV_SHIFT 27 -#define QCA953X_SRIF_DPLL1_REFDIV_MASK 0x1f +#define QCA953X_SRIF_DPLL1_REFDIV_SHIFT 27 +#define QCA953X_SRIF_DPLL1_REFDIV_MASK 0x1f -#define QCA953X_SRIF_DPLL1_NINT_SHIFT 18 -#define QCA953X_SRIF_DPLL1_NINT_MASK 0x1ff -#define QCA953X_SRIF_DPLL1_NFRAC_MASK 0x0003ffff +#define QCA953X_SRIF_DPLL1_NINT_SHIFT 18 +#define QCA953X_SRIF_DPLL1_NINT_MASK 0x1ff +#define QCA953X_SRIF_DPLL1_NFRAC_MASK 0x0003ffff -#define QCA953X_SRIF_DPLL2_LOCAL_PLL BIT(30) +#define QCA953X_SRIF_DPLL2_LOCAL_PLL BIT(30) -#define QCA953X_SRIF_DPLL2_KI_SHIFT 29 -#define QCA953X_SRIF_DPLL2_KI_MASK 0x3 +#define QCA953X_SRIF_DPLL2_KI_SHIFT 29 +#define QCA953X_SRIF_DPLL2_KI_MASK 0x3 -#define QCA953X_SRIF_DPLL2_KD_SHIFT 25 -#define QCA953X_SRIF_DPLL2_KD_MASK 0xf +#define QCA953X_SRIF_DPLL2_KD_SHIFT 25 +#define QCA953X_SRIF_DPLL2_KD_MASK 0xf -#define QCA953X_SRIF_DPLL2_PWD BIT(22) +#define QCA953X_SRIF_DPLL2_PWD BIT(22) -#define QCA953X_SRIF_DPLL2_OUTDIV_SHIFT 13 -#define QCA953X_SRIF_DPLL2_OUTDIV_MASK 0x7 +#define QCA953X_SRIF_DPLL2_OUTDIV_SHIFT 13 +#define QCA953X_SRIF_DPLL2_OUTDIV_MASK 0x7 /* * MII_CTRL block */ -#define AR71XX_MII_REG_MII0_CTRL 0x00 -#define AR71XX_MII_REG_MII1_CTRL 0x04 +#define AR71XX_MII_REG_MII0_CTRL 0x00 +#define AR71XX_MII_REG_MII1_CTRL 0x04 -#define AR71XX_MII_CTRL_IF_MASK 3 -#define AR71XX_MII_CTRL_SPEED_SHIFT 4 -#define AR71XX_MII_CTRL_SPEED_MASK 3 -#define AR71XX_MII_CTRL_SPEED_10 0 -#define AR71XX_MII_CTRL_SPEED_100 1 -#define AR71XX_MII_CTRL_SPEED_1000 2 +#define AR71XX_MII_CTRL_IF_MASK 3 +#define AR71XX_MII_CTRL_SPEED_SHIFT 4 +#define AR71XX_MII_CTRL_SPEED_MASK 3 +#define AR71XX_MII_CTRL_SPEED_10 0 +#define AR71XX_MII_CTRL_SPEED_100 1 +#define AR71XX_MII_CTRL_SPEED_1000 2 -#define AR71XX_MII0_CTRL_IF_GMII 0 -#define AR71XX_MII0_CTRL_IF_MII 1 -#define AR71XX_MII0_CTRL_IF_RGMII 2 -#define AR71XX_MII0_CTRL_IF_RMII 3 +#define AR71XX_MII0_CTRL_IF_GMII 0 +#define AR71XX_MII0_CTRL_IF_MII 1 +#define AR71XX_MII0_CTRL_IF_RGMII 2 +#define AR71XX_MII0_CTRL_IF_RMII 3 -#define AR71XX_MII1_CTRL_IF_RGMII 0 -#define AR71XX_MII1_CTRL_IF_RMII 1 +#define AR71XX_MII1_CTRL_IF_RGMII 0 +#define AR71XX_MII1_CTRL_IF_RMII 1 /* * AR933X GMAC interface */ -#define AR933X_GMAC_REG_ETH_CFG 0x00 +#define AR933X_GMAC_REG_ETH_CFG 0x00 -#define AR933X_ETH_CFG_RGMII_GE0 BIT(0) -#define AR933X_ETH_CFG_MII_GE0 BIT(1) -#define AR933X_ETH_CFG_GMII_GE0 BIT(2) -#define AR933X_ETH_CFG_MII_GE0_MASTER BIT(3) -#define AR933X_ETH_CFG_MII_GE0_SLAVE BIT(4) -#define AR933X_ETH_CFG_MII_GE0_ERR_EN BIT(5) -#define AR933X_ETH_CFG_SW_PHY_SWAP BIT(7) -#define AR933X_ETH_CFG_SW_PHY_ADDR_SWAP BIT(8) -#define AR933X_ETH_CFG_RMII_GE0 BIT(9) -#define AR933X_ETH_CFG_RMII_GE0_SPD_10 0 -#define AR933X_ETH_CFG_RMII_GE0_SPD_100 BIT(10) +#define AR933X_ETH_CFG_RGMII_GE0 BIT(0) +#define AR933X_ETH_CFG_MII_GE0 BIT(1) +#define AR933X_ETH_CFG_GMII_GE0 BIT(2) +#define AR933X_ETH_CFG_MII_GE0_MASTER BIT(3) +#define AR933X_ETH_CFG_MII_GE0_SLAVE BIT(4) +#define AR933X_ETH_CFG_MII_GE0_ERR_EN BIT(5) +#define AR933X_ETH_CFG_SW_PHY_SWAP BIT(7) +#define AR933X_ETH_CFG_SW_PHY_ADDR_SWAP BIT(8) +#define AR933X_ETH_CFG_RMII_GE0 BIT(9) +#define AR933X_ETH_CFG_RMII_GE0_SPD_10 0 +#define AR933X_ETH_CFG_RMII_GE0_SPD_100 BIT(10) /* * AR934X GMAC Interface */ -#define AR934X_GMAC_REG_ETH_CFG 0x00 +#define AR934X_GMAC_REG_ETH_CFG 0x00 -#define AR934X_ETH_CFG_RGMII_GMAC0 BIT(0) -#define AR934X_ETH_CFG_MII_GMAC0 BIT(1) -#define AR934X_ETH_CFG_GMII_GMAC0 BIT(2) -#define AR934X_ETH_CFG_MII_GMAC0_MASTER BIT(3) -#define AR934X_ETH_CFG_MII_GMAC0_SLAVE BIT(4) -#define AR934X_ETH_CFG_MII_GMAC0_ERR_EN BIT(5) -#define AR934X_ETH_CFG_SW_ONLY_MODE BIT(6) -#define AR934X_ETH_CFG_SW_PHY_SWAP BIT(7) -#define AR934X_ETH_CFG_SW_APB_ACCESS BIT(9) -#define AR934X_ETH_CFG_RMII_GMAC0 BIT(10) -#define AR933X_ETH_CFG_MII_CNTL_SPEED BIT(11) -#define AR934X_ETH_CFG_RMII_GMAC0_MASTER BIT(12) -#define AR933X_ETH_CFG_SW_ACC_MSB_FIRST BIT(13) -#define AR934X_ETH_CFG_RXD_DELAY BIT(14) -#define AR934X_ETH_CFG_RXD_DELAY_MASK 0x3 -#define AR934X_ETH_CFG_RXD_DELAY_SHIFT 14 -#define AR934X_ETH_CFG_RDV_DELAY BIT(16) -#define AR934X_ETH_CFG_RDV_DELAY_MASK 0x3 -#define AR934X_ETH_CFG_RDV_DELAY_SHIFT 16 +#define AR934X_ETH_CFG_RGMII_GMAC0 BIT(0) +#define AR934X_ETH_CFG_MII_GMAC0 BIT(1) +#define AR934X_ETH_CFG_GMII_GMAC0 BIT(2) +#define AR934X_ETH_CFG_MII_GMAC0_MASTER BIT(3) +#define AR934X_ETH_CFG_MII_GMAC0_SLAVE BIT(4) +#define AR934X_ETH_CFG_MII_GMAC0_ERR_EN BIT(5) +#define AR934X_ETH_CFG_SW_ONLY_MODE BIT(6) +#define AR934X_ETH_CFG_SW_PHY_SWAP BIT(7) +#define AR934X_ETH_CFG_SW_APB_ACCESS BIT(9) +#define AR934X_ETH_CFG_RMII_GMAC0 BIT(10) +#define AR933X_ETH_CFG_MII_CNTL_SPEED BIT(11) +#define AR934X_ETH_CFG_RMII_GMAC0_MASTER BIT(12) +#define AR933X_ETH_CFG_SW_ACC_MSB_FIRST BIT(13) +#define AR934X_ETH_CFG_RXD_DELAY BIT(14) +#define AR934X_ETH_CFG_RXD_DELAY_MASK 0x3 +#define AR934X_ETH_CFG_RXD_DELAY_SHIFT 14 +#define AR934X_ETH_CFG_RDV_DELAY BIT(16) +#define AR934X_ETH_CFG_RDV_DELAY_MASK 0x3 +#define AR934X_ETH_CFG_RDV_DELAY_SHIFT 16 /* * QCA953X GMAC Interface */ -#define QCA953X_GMAC_REG_ETH_CFG 0x00 +#define QCA953X_GMAC_REG_ETH_CFG 0x00 -#define QCA953X_ETH_CFG_SW_ONLY_MODE BIT(6) -#define QCA953X_ETH_CFG_SW_PHY_SWAP BIT(7) -#define QCA953X_ETH_CFG_SW_APB_ACCESS BIT(9) -#define QCA953X_ETH_CFG_SW_ACC_MSB_FIRST BIT(13) +#define QCA953X_ETH_CFG_SW_ONLY_MODE BIT(6) +#define QCA953X_ETH_CFG_SW_PHY_SWAP BIT(7) +#define QCA953X_ETH_CFG_SW_APB_ACCESS BIT(9) +#define QCA953X_ETH_CFG_SW_ACC_MSB_FIRST BIT(13) /* * QCA955X GMAC Interface */ -#define QCA955X_GMAC_REG_ETH_CFG 0x00 +#define QCA955X_GMAC_REG_ETH_CFG 0x00 -#define QCA955X_ETH_CFG_RGMII_EN BIT(0) -#define QCA955X_ETH_CFG_GE0_SGMII BIT(6) +#define QCA955X_ETH_CFG_RGMII_EN BIT(0) +#define QCA955X_ETH_CFG_GE0_SGMII BIT(6) #endif /* __ASM_AR71XX_H */ From 43a092ffdd5edd6a66e8e9ec34372f3abd396486 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Fri, 6 May 2016 20:10:35 +0200 Subject: [PATCH 139/162] mips: ath79: Fix compiler warning on const assignment The assignment const T var; var = value; is illegal, since var is constant. Drop the const to fix the compiler warning. Signed-off-by: Marek Vasut Cc: Daniel Schwierzeck Cc: Wills Wang --- arch/mips/mach-ath79/reset.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/mips/mach-ath79/reset.c b/arch/mips/mach-ath79/reset.c index 2ea2f8d3ac..ba38609a16 100644 --- a/arch/mips/mach-ath79/reset.c +++ b/arch/mips/mach-ath79/reset.c @@ -46,7 +46,7 @@ void _machine_restart(void) u32 get_bootstrap(void) { - const void __iomem *base; + void __iomem *base; u32 reg = 0; base = map_physmem(AR71XX_RESET_BASE, AR71XX_RESET_SIZE, From c31558780b50883bbbbb657592dc3391b2551353 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Fri, 6 May 2016 20:10:36 +0200 Subject: [PATCH 140/162] mips: ath79: dts: Add generic-ehci node Add generic EHCI node for the ChipIdea EHCI controller in the ath79. Signed-off-by: Marek Vasut Cc: Daniel Schwierzeck Cc: Wills Wang --- arch/mips/dts/ar933x.dtsi | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/arch/mips/dts/ar933x.dtsi b/arch/mips/dts/ar933x.dtsi index 11f60a2864..2e124a49b3 100644 --- a/arch/mips/dts/ar933x.dtsi +++ b/arch/mips/dts/ar933x.dtsi @@ -59,6 +59,13 @@ #address-cells = <1>; #size-cells = <1>; + ehci0: ehci@1b000100 { + compatible = "generic-ehci"; + reg = <0x1b000100 0x100>; + + status = "disabled"; + }; + uart0: uart@18020000 { compatible = "qca,ar9330-uart"; reg = <0x18020000 0x20>; From 6b699742d4795804d553deaf5163a0923bd27274 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Fri, 6 May 2016 20:10:37 +0200 Subject: [PATCH 141/162] mips: ath79: Add support for ungating USB on ar933x and ar934x Add code to ungate the USB controller on ar933x and ar934x . Signed-off-by: Marek Vasut Cc: Daniel Schwierzeck Cc: Wills Wang --- arch/mips/mach-ath79/include/mach/ath79.h | 2 + arch/mips/mach-ath79/reset.c | 59 +++++++++++++++++++++++ 2 files changed, 61 insertions(+) diff --git a/arch/mips/mach-ath79/include/mach/ath79.h b/arch/mips/mach-ath79/include/mach/ath79.h index 90d80b8bc8..682b6a2ee5 100644 --- a/arch/mips/mach-ath79/include/mach/ath79.h +++ b/arch/mips/mach-ath79/include/mach/ath79.h @@ -140,4 +140,6 @@ static inline int soc_is_qca956x(void) return soc_is_tp9343() || soc_is_qca9561(); } +int ath79_usb_reset(void); + #endif /* __ASM_MACH_ATH79_H */ diff --git a/arch/mips/mach-ath79/reset.c b/arch/mips/mach-ath79/reset.c index ba38609a16..1538e321bc 100644 --- a/arch/mips/mach-ath79/reset.c +++ b/arch/mips/mach-ath79/reset.c @@ -5,6 +5,7 @@ */ #include +#include #include #include #include @@ -69,3 +70,61 @@ u32 get_bootstrap(void) return 0; } + +static int usb_reset_ar933x(void __iomem *reset_regs) +{ + /* Ungate the USB block */ + setbits_be32(reset_regs + AR933X_RESET_REG_RESET_MODULE, + AR933X_RESET_USBSUS_OVERRIDE); + mdelay(1); + clrbits_be32(reset_regs + AR933X_RESET_REG_RESET_MODULE, + AR933X_RESET_USB_HOST); + mdelay(1); + clrbits_be32(reset_regs + AR933X_RESET_REG_RESET_MODULE, + AR933X_RESET_USB_PHY); + mdelay(1); + + return 0; +} + +static int usb_reset_ar934x(void __iomem *reset_regs) +{ + /* Ungate the USB block */ + setbits_be32(reset_regs + AR934X_RESET_REG_RESET_MODULE, + AR934X_RESET_USBSUS_OVERRIDE); + mdelay(1); + clrbits_be32(reset_regs + AR934X_RESET_REG_RESET_MODULE, + AR934X_RESET_USB_PHY); + mdelay(1); + clrbits_be32(reset_regs + AR934X_RESET_REG_RESET_MODULE, + AR934X_RESET_USB_PHY_ANALOG); + mdelay(1); + clrbits_be32(reset_regs + AR934X_RESET_REG_RESET_MODULE, + AR934X_RESET_USB_HOST); + mdelay(1); + + return 0; +} + +int ath79_usb_reset(void) +{ + void __iomem *usbc_regs = map_physmem(AR71XX_USB_CTRL_BASE, + AR71XX_USB_CTRL_SIZE, + MAP_NOCACHE); + void __iomem *reset_regs = map_physmem(AR71XX_RESET_BASE, + AR71XX_RESET_SIZE, + MAP_NOCACHE); + /* + * Turn on the Buff and Desc swap bits. + * NOTE: This write into an undocumented register in mandatory to + * get the USB controller operational in BigEndian mode. + */ + writel(0xf0000, usbc_regs + AR71XX_USB_CTRL_REG_CONFIG); + + if (soc_is_ar933x()) + return usb_reset_ar933x(reset_regs); + if (soc_is_ar934x()) + return usb_reset_ar934x(reset_regs); + + return -EINVAL; +} From 2986a9d4bd2197ff3db16c8a4f61574b5a5cca49 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Fri, 6 May 2016 20:10:38 +0200 Subject: [PATCH 142/162] mips: ath79: dts: Add ethernet MAC nodes for ar933x Add node for both ethernet controllers in the ar933x. The PHY is attached only to the first ethernet controller. Signed-off-by: Marek Vasut Cc: Daniel Schwierzeck Cc: Wills Wang --- arch/mips/dts/ar933x.dtsi | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/arch/mips/dts/ar933x.dtsi b/arch/mips/dts/ar933x.dtsi index 2e124a49b3..00896b2be4 100644 --- a/arch/mips/dts/ar933x.dtsi +++ b/arch/mips/dts/ar933x.dtsi @@ -73,6 +73,32 @@ status = "disabled"; }; + + gmac0: eth@0x19000000 { + compatible = "qca,ag7240-mac"; + reg = <0x19000000 0x200>; + phy = <&phy0>; + phy-mode = "rmii"; + + status = "disabled"; + + mdio { + #address-cells = <1>; + #size-cells = <0>; + phy0: ethernet-phy@0 { + reg = <0>; + }; + }; + }; + + gmac1: eth@0x1a000000 { + compatible = "qca,ag7240-mac"; + reg = <0x1a000000 0x200>; + phy = <&phy0>; + phy-mode = "rgmii"; + + status = "disabled"; + }; }; spi0: spi@1f000000 { From 4771bbee5d7f7857de47794e9636783d55c438f6 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Fri, 6 May 2016 20:10:39 +0200 Subject: [PATCH 143/162] mips: ath79: Add support for ungating ethernet on ar933x and ar934x Add code to ungate the ethernet controller on ar933x and ar934x . Signed-off-by: Marek Vasut Cc: Daniel Schwierzeck Cc: Wills Wang --- .../mach-ath79/include/mach/ar71xx_regs.h | 1 + arch/mips/mach-ath79/include/mach/ath79.h | 1 + arch/mips/mach-ath79/reset.c | 78 +++++++++++++++++++ 3 files changed, 80 insertions(+) diff --git a/arch/mips/mach-ath79/include/mach/ar71xx_regs.h b/arch/mips/mach-ath79/include/mach/ar71xx_regs.h index bff9d0594d..a9630c081b 100644 --- a/arch/mips/mach-ath79/include/mach/ar71xx_regs.h +++ b/arch/mips/mach-ath79/include/mach/ar71xx_regs.h @@ -622,6 +622,7 @@ #define AR933X_RESET_GE1_MAC BIT(13) #define AR933X_RESET_WMAC BIT(11) #define AR933X_RESET_GE0_MAC BIT(9) +#define AR933X_RESET_ETH_SWITCH BIT(8) #define AR933X_RESET_USB_HOST BIT(5) #define AR933X_RESET_USB_PHY BIT(4) #define AR933X_RESET_USBSUS_OVERRIDE BIT(3) diff --git a/arch/mips/mach-ath79/include/mach/ath79.h b/arch/mips/mach-ath79/include/mach/ath79.h index 682b6a2ee5..2c6c118176 100644 --- a/arch/mips/mach-ath79/include/mach/ath79.h +++ b/arch/mips/mach-ath79/include/mach/ath79.h @@ -140,6 +140,7 @@ static inline int soc_is_qca956x(void) return soc_is_tp9343() || soc_is_qca9561(); } +int ath79_eth_reset(void); int ath79_usb_reset(void); #endif /* __ASM_MACH_ATH79_H */ diff --git a/arch/mips/mach-ath79/reset.c b/arch/mips/mach-ath79/reset.c index 1538e321bc..188eccb9bf 100644 --- a/arch/mips/mach-ath79/reset.c +++ b/arch/mips/mach-ath79/reset.c @@ -71,6 +71,84 @@ u32 get_bootstrap(void) return 0; } +static int eth_init_ar933x(void) +{ + void __iomem *rregs = map_physmem(AR71XX_RESET_BASE, AR71XX_RESET_SIZE, + MAP_NOCACHE); + void __iomem *pregs = map_physmem(AR71XX_PLL_BASE, AR71XX_PLL_SIZE, + MAP_NOCACHE); + void __iomem *gregs = map_physmem(AR933X_GMAC_BASE, AR933X_GMAC_SIZE, + MAP_NOCACHE); + const u32 mask = AR933X_RESET_GE0_MAC | AR933X_RESET_GE0_MDIO | + AR933X_RESET_GE1_MAC | AR933X_RESET_GE1_MDIO | + AR933X_RESET_ETH_SWITCH; + + /* Clear MDIO slave EN bit. */ + clrbits_be32(rregs + AR933X_RESET_REG_BOOTSTRAP, BIT(17)); + mdelay(10); + + /* Get Atheros S26 PHY out of reset. */ + clrsetbits_be32(pregs + AR934X_PLL_SWITCH_CLOCK_CONTROL_REG, + 0x1f, 0x10); + mdelay(10); + + setbits_be32(rregs + AR933X_RESET_REG_RESET_MODULE, mask); + mdelay(10); + clrbits_be32(rregs + AR933X_RESET_REG_RESET_MODULE, mask); + mdelay(10); + + /* Configure AR93xx GMAC register. */ + clrsetbits_be32(gregs + AR933X_GMAC_REG_ETH_CFG, + AR933X_ETH_CFG_MII_GE0_MASTER | + AR933X_ETH_CFG_MII_GE0_SLAVE, + AR933X_ETH_CFG_MII_GE0_SLAVE); + return 0; +} + +static int eth_init_ar934x(void) +{ + void __iomem *rregs = map_physmem(AR71XX_RESET_BASE, AR71XX_RESET_SIZE, + MAP_NOCACHE); + void __iomem *pregs = map_physmem(AR71XX_PLL_BASE, AR71XX_PLL_SIZE, + MAP_NOCACHE); + void __iomem *gregs = map_physmem(AR934X_GMAC_BASE, AR934X_GMAC_SIZE, + MAP_NOCACHE); + const u32 mask = AR934X_RESET_GE0_MAC | AR934X_RESET_GE0_MDIO | + AR934X_RESET_GE1_MAC | AR934X_RESET_GE1_MDIO | + AR934X_RESET_ETH_SWITCH_ANALOG; + u32 reg; + + reg = readl(rregs + AR934X_RESET_REG_BOOTSTRAP); + if (reg & AR934X_BOOTSTRAP_REF_CLK_40) + writel(0x570, pregs + AR934X_PLL_SWITCH_CLOCK_CONTROL_REG); + else + writel(0x271, pregs + AR934X_PLL_SWITCH_CLOCK_CONTROL_REG); + writel(BIT(26) | BIT(25), pregs + AR934X_PLL_ETH_XMII_CONTROL_REG); + + setbits_be32(rregs + AR934X_RESET_REG_RESET_MODULE, mask); + mdelay(1); + clrbits_be32(rregs + AR934X_RESET_REG_RESET_MODULE, mask); + mdelay(1); + + /* Configure AR934x GMAC register. */ + writel(AR934X_ETH_CFG_RGMII_GMAC0, gregs + AR934X_GMAC_REG_ETH_CFG); + return 0; +} + +int ath79_eth_reset(void) +{ + /* + * Un-reset ethernet. DM still doesn't have any notion of reset + * framework, so we do it by hand here. + */ + if (soc_is_ar933x()) + return eth_init_ar933x(); + if (soc_is_ar934x()) + return eth_init_ar934x(); + + return -EINVAL; +} + static int usb_reset_ar933x(void __iomem *reset_regs) { /* Ungate the USB block */ From e08539b791336c45ca05ebdf55137a26baaba95e Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Fri, 6 May 2016 20:10:40 +0200 Subject: [PATCH 144/162] mips: ath79: Add AR934x support Add support for the Atheros AR934x WiSoCs. This patchs adds complete system init, including PLL and DRAM init, both of which happen from full C environment, since the AR934x has proper SRAM. Signed-off-by: Marek Vasut Cc: Daniel Schwierzeck Cc: Wills Wang --- arch/mips/dts/ar934x.dtsi | 112 ++++++ arch/mips/mach-ath79/Kconfig | 9 + arch/mips/mach-ath79/Makefile | 3 +- arch/mips/mach-ath79/ar934x/Makefile | 7 + arch/mips/mach-ath79/ar934x/clk.c | 334 ++++++++++++++++++ arch/mips/mach-ath79/ar934x/cpu.c | 10 + arch/mips/mach-ath79/ar934x/ddr.c | 163 +++++++++ .../mach-ath79/include/mach/ar71xx_regs.h | 43 +++ arch/mips/mach-ath79/include/mach/ath79.h | 3 + 9 files changed, 683 insertions(+), 1 deletion(-) create mode 100644 arch/mips/dts/ar934x.dtsi create mode 100644 arch/mips/mach-ath79/ar934x/Makefile create mode 100644 arch/mips/mach-ath79/ar934x/clk.c create mode 100644 arch/mips/mach-ath79/ar934x/cpu.c create mode 100644 arch/mips/mach-ath79/ar934x/ddr.c diff --git a/arch/mips/dts/ar934x.dtsi b/arch/mips/dts/ar934x.dtsi new file mode 100644 index 0000000000..7a036a8f94 --- /dev/null +++ b/arch/mips/dts/ar934x.dtsi @@ -0,0 +1,112 @@ +/* + * Copyright (C) 2016 Marek Vasut + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include "skeleton.dtsi" + +/ { + compatible = "qca,ar934x"; + + #address-cells = <1>; + #size-cells = <1>; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + + cpu@0 { + device_type = "cpu"; + compatible = "mips,mips74Kc"; + reg = <0>; + }; + }; + + clocks { + #address-cells = <1>; + #size-cells = <1>; + ranges; + + xtal: xtal { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-output-names = "xtal"; + }; + }; + + ahb { + compatible = "simple-bus"; + ranges; + + #address-cells = <1>; + #size-cells = <1>; + + apb { + compatible = "simple-bus"; + ranges; + + #address-cells = <1>; + #size-cells = <1>; + + ehci0: ehci@1b000100 { + compatible = "generic-ehci"; + reg = <0x1b000100 0x100>; + + status = "disabled"; + }; + + uart0: uart@18020000 { + compatible = "ns16550"; + reg = <0x18020000 0x20>; + reg-shift = <2>; + + status = "disabled"; + }; + + gmac0: eth@0x19000000 { + compatible = "qca,ag934x-mac"; + reg = <0x19000000 0x200>; + phy = <&phy0>; + phy-mode = "rgmii"; + + status = "disabled"; + + mdio { + #address-cells = <1>; + #size-cells = <0>; + phy0: ethernet-phy@0 { + reg = <0>; + }; + }; + }; + + gmac1: eth@0x1a000000 { + compatible = "qca,ag934x-mac"; + reg = <0x1a000000 0x200>; + phy = <&phy1>; + phy-mode = "rgmii"; + + status = "disabled"; + + mdio { + #address-cells = <1>; + #size-cells = <0>; + phy1: ethernet-phy@0 { + reg = <0>; + }; + }; + }; + }; + + spi0: spi@1f000000 { + compatible = "qca,ar7100-spi"; + reg = <0x1f000000 0x10>; + + status = "disabled"; + + #address-cells = <1>; + #size-cells = <0>; + }; + }; +}; diff --git a/arch/mips/mach-ath79/Kconfig b/arch/mips/mach-ath79/Kconfig index f45403bda9..527960f4eb 100644 --- a/arch/mips/mach-ath79/Kconfig +++ b/arch/mips/mach-ath79/Kconfig @@ -13,6 +13,15 @@ config SOC_AR933X help This supports QCA/Atheros ar933x family SOCs. +config SOC_AR934X + bool + select SUPPORTS_BIG_ENDIAN + select SUPPORTS_CPU_MIPS32_R1 + select SUPPORTS_CPU_MIPS32_R2 + select MIPS_TUNE_74KC + help + This supports QCA/Atheros ar934x family SOCs. + config SOC_QCA953X bool select SUPPORTS_BIG_ENDIAN diff --git a/arch/mips/mach-ath79/Makefile b/arch/mips/mach-ath79/Makefile index 160dfaa146..d7e2666a7c 100644 --- a/arch/mips/mach-ath79/Makefile +++ b/arch/mips/mach-ath79/Makefile @@ -7,4 +7,5 @@ obj-y += cpu.o obj-y += dram.o obj-$(CONFIG_SOC_AR933X) += ar933x/ -obj-$(CONFIG_SOC_QCA953X) += qca953x/ \ No newline at end of file +obj-$(CONFIG_SOC_AR934X) += ar934x/ +obj-$(CONFIG_SOC_QCA953X) += qca953x/ diff --git a/arch/mips/mach-ath79/ar934x/Makefile b/arch/mips/mach-ath79/ar934x/Makefile new file mode 100644 index 0000000000..348c65b253 --- /dev/null +++ b/arch/mips/mach-ath79/ar934x/Makefile @@ -0,0 +1,7 @@ +# +# SPDX-License-Identifier: GPL-2.0+ +# + +obj-y += cpu.o +obj-y += clk.o +obj-y += ddr.o diff --git a/arch/mips/mach-ath79/ar934x/clk.c b/arch/mips/mach-ath79/ar934x/clk.c new file mode 100644 index 0000000000..9c65184e7a --- /dev/null +++ b/arch/mips/mach-ath79/ar934x/clk.c @@ -0,0 +1,334 @@ +/* + * Copyright (C) 2016 Marek Vasut + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include +#include +#include +#include + +DECLARE_GLOBAL_DATA_PTR; + +/* + * The math for calculating PLL: + * NFRAC * 2^8 + * NINT + ------------- + * XTAL [MHz] 2^(18 - 1) + * PLL [MHz] = ------------ * ---------------------- + * REFDIV 2^OUTDIV + * + * Unfortunatelly, there is no way to reliably compute the variables. + * The vendor U-Boot port contains macros for various combinations of + * CPU PLL / DDR PLL / AHB bus speed and there is no obvious pattern + * in those numbers. + */ +struct ar934x_pll_config { + u8 range; + u8 refdiv; + u8 outdiv; + /* Index 0 is for XTAL=25MHz , Index 1 is for XTAL=40MHz */ + u8 nint[2]; +}; + +struct ar934x_clock_config { + u16 cpu_freq; + u16 ddr_freq; + u16 ahb_freq; + + struct ar934x_pll_config cpu_pll; + struct ar934x_pll_config ddr_pll; +}; + +static const struct ar934x_clock_config ar934x_clock_config[] = { + { 300, 300, 150, { 1, 1, 1, { 24, 15 } }, { 1, 1, 1, { 24, 15 } } }, + { 400, 200, 200, { 1, 1, 1, { 32, 20 } }, { 1, 1, 2, { 32, 20 } } }, + { 400, 400, 200, { 0, 1, 1, { 32, 20 } }, { 0, 1, 1, { 32, 20 } } }, + { 500, 400, 200, { 1, 1, 0, { 20, 12 } }, { 0, 1, 1, { 32, 20 } } }, + { 533, 400, 200, { 1, 1, 0, { 21, 13 } }, { 0, 1, 1, { 32, 20 } } }, + { 533, 500, 250, { 1, 1, 0, { 21, 13 } }, { 0, 1, 0, { 20, 12 } } }, + { 560, 480, 240, { 1, 1, 0, { 22, 14 } }, { 1, 1, 0, { 19, 12 } } }, + { 566, 400, 200, { 1, 1, 0, { 22, 14 } }, { 1, 1, 0, { 16, 10 } } }, + { 566, 450, 225, { 1, 1, 0, { 22, 14 } }, { 0, 1, 1, { 36, 22 } } }, + { 566, 475, 237, { 1, 1, 0, { 22, 14 } }, { 1, 1, 0, { 19, 11 } } }, + { 566, 500, 250, { 1, 1, 0, { 22, 14 } }, { 1, 1, 0, { 20, 12 } } }, + { 566, 525, 262, { 1, 1, 0, { 22, 14 } }, { 1, 1, 0, { 21, 13 } } }, + { 566, 550, 275, { 1, 1, 0, { 22, 14 } }, { 1, 1, 0, { 22, 13 } } }, + { 600, 266, 133, { 0, 1, 0, { 24, 15 } }, { 1, 1, 1, { 21, 16 } } }, + { 600, 266, 200, { 0, 1, 0, { 24, 15 } }, { 1, 1, 1, { 21, 16 } } }, + { 600, 300, 150, { 0, 1, 0, { 24, 15 } }, { 0, 1, 1, { 24, 15 } } }, + { 600, 332, 166, { 0, 1, 0, { 24, 15 } }, { 1, 1, 1, { 26, 16 } } }, + { 600, 332, 200, { 0, 1, 0, { 24, 15 } }, { 1, 1, 1, { 26, 16 } } }, + { 600, 400, 200, { 0, 1, 0, { 24, 15 } }, { 0, 1, 1, { 32, 20 } } }, + { 600, 450, 200, { 0, 1, 0, { 24, 15 } }, { 0, 1, 0, { 18, 20 } } }, + { 600, 500, 250, { 0, 1, 0, { 24, 15 } }, { 1, 1, 0, { 20, 12 } } }, + { 600, 525, 262, { 0, 1, 0, { 24, 15 } }, { 0, 1, 0, { 21, 20 } } }, + { 600, 550, 275, { 0, 1, 0, { 24, 15 } }, { 0, 1, 0, { 22, 20 } } }, + { 600, 575, 287, { 0, 1, 0, { 24, 15 } }, { 0, 1, 0, { 23, 14 } } }, + { 600, 600, 300, { 0, 1, 0, { 24, 15 } }, { 0, 1, 0, { 24, 20 } } }, + { 600, 650, 325, { 0, 1, 0, { 24, 15 } }, { 0, 1, 0, { 26, 20 } } }, + { 650, 600, 300, { 0, 1, 0, { 26, 15 } }, { 0, 1, 0, { 24, 20 } } }, + { 700, 400, 200, { 3, 1, 0, { 28, 17 } }, { 0, 1, 1, { 32, 20 } } }, +}; + +static void ar934x_srif_pll_cfg(void __iomem *pll_reg_base, const u32 srif_val) +{ + u32 reg; + do { + writel(0x10810f00, pll_reg_base + 0x4); + writel(srif_val, pll_reg_base + 0x0); + writel(0xd0810f00, pll_reg_base + 0x4); + writel(0x03000000, pll_reg_base + 0x8); + writel(0xd0800f00, pll_reg_base + 0x4); + + clrbits_be32(pll_reg_base + 0x8, BIT(30)); + udelay(5); + setbits_be32(pll_reg_base + 0x8, BIT(30)); + udelay(5); + + wait_for_bit("clk", pll_reg_base + 0xc, BIT(3), 1, 10, 0); + + clrbits_be32(pll_reg_base + 0x8, BIT(30)); + udelay(5); + + /* Check if CPU SRIF PLL locked. */ + reg = readl(pll_reg_base + 0x8); + reg = (reg & 0x7ffff8) >> 3; + } while (reg >= 0x40000); +} + +void ar934x_pll_init(const u16 cpu_mhz, const u16 ddr_mhz, const u16 ahb_mhz) +{ + void __iomem *srif_regs = map_physmem(AR934X_SRIF_BASE, + AR934X_SRIF_SIZE, MAP_NOCACHE); + void __iomem *pll_regs = map_physmem(AR71XX_PLL_BASE, + AR71XX_PLL_SIZE, MAP_NOCACHE); + const struct ar934x_pll_config *pll_cfg; + int i, pll_nint, pll_refdiv, xtal_40 = 0; + u32 reg, cpu_pll, cpu_srif, ddr_pll, ddr_srif; + + /* Configure SRIF PLL with initial values. */ + writel(0x13210f00, srif_regs + AR934X_SRIF_CPU_DPLL2_REG); + writel(0x03000000, srif_regs + AR934X_SRIF_CPU_DPLL3_REG); + writel(0x13210f00, srif_regs + AR934X_SRIF_DDR_DPLL2_REG); + writel(0x03000000, srif_regs + AR934X_SRIF_DDR_DPLL3_REG); + writel(0x03000000, srif_regs + 0x188); /* Undocumented reg :-) */ + + /* Test for 40MHz XTAL */ + reg = get_bootstrap(); + if (reg & AR934X_BOOTSTRAP_REF_CLK_40) { + xtal_40 = 1; + cpu_srif = 0x41c00000; + ddr_srif = 0x41680000; + } else { + xtal_40 = 0; + cpu_srif = 0x29c00000; + ddr_srif = 0x29680000; + } + + /* Locate CPU/DDR PLL configuration */ + for (i = 0; i < ARRAY_SIZE(ar934x_clock_config); i++) { + if (cpu_mhz != ar934x_clock_config[i].cpu_freq) + continue; + if (ddr_mhz != ar934x_clock_config[i].ddr_freq) + continue; + if (ahb_mhz != ar934x_clock_config[i].ahb_freq) + continue; + + /* Entry found */ + pll_cfg = &ar934x_clock_config[i].cpu_pll; + pll_nint = pll_cfg->nint[xtal_40]; + pll_refdiv = pll_cfg->refdiv; + cpu_pll = + (pll_nint << AR934X_PLL_CPU_CONFIG_NINT_SHIFT) | + (pll_refdiv << AR934X_PLL_CPU_CONFIG_REFDIV_SHIFT) | + (pll_cfg->range << AR934X_PLL_CPU_CONFIG_RANGE_SHIFT) | + (pll_cfg->outdiv << AR934X_PLL_CPU_CONFIG_OUTDIV_SHIFT); + + pll_cfg = &ar934x_clock_config[i].ddr_pll; + pll_nint = pll_cfg->nint[xtal_40]; + pll_refdiv = pll_cfg->refdiv; + ddr_pll = + (pll_nint << AR934X_PLL_DDR_CONFIG_NINT_SHIFT) | + (pll_refdiv << AR934X_PLL_DDR_CONFIG_REFDIV_SHIFT) | + (pll_cfg->range << AR934X_PLL_DDR_CONFIG_RANGE_SHIFT) | + (pll_cfg->outdiv << AR934X_PLL_DDR_CONFIG_OUTDIV_SHIFT); + break; + } + + /* PLL configuration not found, hang. */ + if (i == ARRAY_SIZE(ar934x_clock_config)) + hang(); + + /* Set PLL Bypass */ + setbits_be32(pll_regs + AR934X_PLL_CPU_DDR_CLK_CTRL_REG, + AR934X_PLL_CLK_CTRL_CPU_PLL_BYPASS); + setbits_be32(pll_regs + AR934X_PLL_CPU_DDR_CLK_CTRL_REG, + AR934X_PLL_CLK_CTRL_DDR_PLL_BYPASS); + setbits_be32(pll_regs + AR934X_PLL_CPU_DDR_CLK_CTRL_REG, + AR934X_PLL_CLK_CTRL_AHB_PLL_BYPASS); + + /* Configure CPU PLL */ + writel(cpu_pll | AR934X_PLL_CPU_CONFIG_PLLPWD, + pll_regs + AR934X_PLL_CPU_CONFIG_REG); + /* Configure DDR PLL */ + writel(ddr_pll | AR934X_PLL_DDR_CONFIG_PLLPWD, + pll_regs + AR934X_PLL_DDR_CONFIG_REG); + /* Configure PLL routing */ + writel(AR934X_PLL_CLK_CTRL_CPU_PLL_BYPASS | + AR934X_PLL_CLK_CTRL_DDR_PLL_BYPASS | + AR934X_PLL_CLK_CTRL_AHB_PLL_BYPASS | + (0 << AR934X_PLL_CLK_CTRL_CPU_POST_DIV_SHIFT) | + (0 << AR934X_PLL_CLK_CTRL_DDR_POST_DIV_SHIFT) | + (1 << AR934X_PLL_CLK_CTRL_AHB_POST_DIV_SHIFT) | + AR934X_PLL_CLK_CTRL_CPUCLK_FROM_CPUPLL | + AR934X_PLL_CLK_CTRL_DDRCLK_FROM_DDRPLL | + AR934X_PLL_CLK_CTRL_AHBCLK_FROM_DDRPLL, + pll_regs + AR934X_PLL_CPU_DDR_CLK_CTRL_REG); + + /* Configure SRIF PLLs, which is completely undocumented :-) */ + ar934x_srif_pll_cfg(srif_regs + AR934X_SRIF_CPU_DPLL1_REG, cpu_srif); + ar934x_srif_pll_cfg(srif_regs + AR934X_SRIF_DDR_DPLL1_REG, ddr_srif); + + /* Unset PLL Bypass */ + clrbits_be32(pll_regs + AR934X_PLL_CPU_DDR_CLK_CTRL_REG, + AR934X_PLL_CLK_CTRL_CPU_PLL_BYPASS); + clrbits_be32(pll_regs + AR934X_PLL_CPU_DDR_CLK_CTRL_REG, + AR934X_PLL_CLK_CTRL_DDR_PLL_BYPASS); + clrbits_be32(pll_regs + AR934X_PLL_CPU_DDR_CLK_CTRL_REG, + AR934X_PLL_CLK_CTRL_AHB_PLL_BYPASS); + + /* Enable PLL dithering */ + writel((1 << AR934X_PLL_DDR_DIT_FRAC_STEP_SHIFT) | + (0xf << AR934X_PLL_DDR_DIT_UPD_CNT_SHIFT), + pll_regs + AR934X_PLL_DDR_DIT_FRAC_REG); + writel(48 << AR934X_PLL_CPU_DIT_UPD_CNT_SHIFT, + pll_regs + AR934X_PLL_CPU_DIT_FRAC_REG); +} + +static u32 ar934x_get_xtal(void) +{ + u32 val; + + val = get_bootstrap(); + if (val & AR934X_BOOTSTRAP_REF_CLK_40) + return 40000000; + else + return 25000000; +} + +int get_serial_clock(void) +{ + return ar934x_get_xtal(); +} + +static u32 ar934x_cpupll_to_hz(const u32 regval) +{ + const u32 outdiv = (regval >> AR934X_PLL_CPU_CONFIG_OUTDIV_SHIFT) & + AR934X_PLL_CPU_CONFIG_OUTDIV_MASK; + const u32 refdiv = (regval >> AR934X_PLL_CPU_CONFIG_REFDIV_SHIFT) & + AR934X_PLL_CPU_CONFIG_REFDIV_MASK; + const u32 nint = (regval >> AR934X_PLL_CPU_CONFIG_NINT_SHIFT) & + AR934X_PLL_CPU_CONFIG_NINT_MASK; + const u32 nfrac = (regval >> AR934X_PLL_CPU_CONFIG_NFRAC_SHIFT) & + AR934X_PLL_CPU_CONFIG_NFRAC_MASK; + const u32 xtal = ar934x_get_xtal(); + + return (xtal * (nint + (nfrac >> 9))) / (refdiv * (1 << outdiv)); +} + +static u32 ar934x_ddrpll_to_hz(const u32 regval) +{ + const u32 outdiv = (regval >> AR934X_PLL_DDR_CONFIG_OUTDIV_SHIFT) & + AR934X_PLL_DDR_CONFIG_OUTDIV_MASK; + const u32 refdiv = (regval >> AR934X_PLL_DDR_CONFIG_REFDIV_SHIFT) & + AR934X_PLL_DDR_CONFIG_REFDIV_MASK; + const u32 nint = (regval >> AR934X_PLL_DDR_CONFIG_NINT_SHIFT) & + AR934X_PLL_DDR_CONFIG_NINT_MASK; + const u32 nfrac = (regval >> AR934X_PLL_DDR_CONFIG_NFRAC_SHIFT) & + AR934X_PLL_DDR_CONFIG_NFRAC_MASK; + const u32 xtal = ar934x_get_xtal(); + + return (xtal * (nint + (nfrac >> 9))) / (refdiv * (1 << outdiv)); +} + +static void ar934x_update_clock(void) +{ + void __iomem *regs; + u32 ctrl, cpu, cpupll, ddr, ddrpll; + u32 cpudiv, ddrdiv, busdiv; + u32 cpuclk, ddrclk, busclk; + + regs = map_physmem(AR71XX_PLL_BASE, AR71XX_PLL_SIZE, + MAP_NOCACHE); + + cpu = readl(regs + AR934X_PLL_CPU_CONFIG_REG); + ddr = readl(regs + AR934X_PLL_DDR_CONFIG_REG); + ctrl = readl(regs + AR934X_PLL_CPU_DDR_CLK_CTRL_REG); + + cpupll = ar934x_cpupll_to_hz(cpu); + ddrpll = ar934x_ddrpll_to_hz(ddr); + + if (ctrl & AR934X_PLL_CLK_CTRL_CPU_PLL_BYPASS) + cpuclk = ar934x_get_xtal(); + else if (ctrl & AR934X_PLL_CLK_CTRL_CPUCLK_FROM_CPUPLL) + cpuclk = cpupll; + else + cpuclk = ddrpll; + + if (ctrl & AR934X_PLL_CLK_CTRL_DDR_PLL_BYPASS) + ddrclk = ar934x_get_xtal(); + else if (ctrl & AR934X_PLL_CLK_CTRL_DDRCLK_FROM_DDRPLL) + ddrclk = ddrpll; + else + ddrclk = cpupll; + + if (ctrl & AR934X_PLL_CLK_CTRL_AHB_PLL_BYPASS) + busclk = ar934x_get_xtal(); + else if (ctrl & AR934X_PLL_CLK_CTRL_AHBCLK_FROM_DDRPLL) + busclk = ddrpll; + else + busclk = cpupll; + + cpudiv = (ctrl >> AR934X_PLL_CLK_CTRL_CPU_POST_DIV_SHIFT) & + AR934X_PLL_CLK_CTRL_CPU_POST_DIV_MASK; + ddrdiv = (ctrl >> AR934X_PLL_CLK_CTRL_DDR_POST_DIV_SHIFT) & + AR934X_PLL_CLK_CTRL_DDR_POST_DIV_MASK; + busdiv = (ctrl >> AR934X_PLL_CLK_CTRL_AHB_POST_DIV_SHIFT) & + AR934X_PLL_CLK_CTRL_AHB_POST_DIV_MASK; + + gd->cpu_clk = cpuclk / (cpudiv + 1); + gd->mem_clk = ddrclk / (ddrdiv + 1); + gd->bus_clk = busclk / (busdiv + 1); +} + +ulong get_bus_freq(ulong dummy) +{ + ar934x_update_clock(); + return gd->bus_clk; +} + +ulong get_ddr_freq(ulong dummy) +{ + ar934x_update_clock(); + return gd->mem_clk; +} + +int do_ar934x_showclk(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + ar934x_update_clock(); + printf("CPU: %8ld MHz\n", gd->cpu_clk / 1000000); + printf("Memory: %8ld MHz\n", gd->mem_clk / 1000000); + printf("AHB: %8ld MHz\n", gd->bus_clk / 1000000); + return 0; +} + +U_BOOT_CMD( + clocks, CONFIG_SYS_MAXARGS, 1, do_ar934x_showclk, + "display clocks", + "" +); diff --git a/arch/mips/mach-ath79/ar934x/cpu.c b/arch/mips/mach-ath79/ar934x/cpu.c new file mode 100644 index 0000000000..8fcdf657d1 --- /dev/null +++ b/arch/mips/mach-ath79/ar934x/cpu.c @@ -0,0 +1,10 @@ +/* + * Copyright (C) 2016 Marek Vasut + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include + +/* The lowlevel_init() is not needed on AR934x */ +void lowlevel_init(void) {} diff --git a/arch/mips/mach-ath79/ar934x/ddr.c b/arch/mips/mach-ath79/ar934x/ddr.c new file mode 100644 index 0000000000..4621d5845c --- /dev/null +++ b/arch/mips/mach-ath79/ar934x/ddr.c @@ -0,0 +1,163 @@ +/* + * Copyright (C) 2016 Marek Vasut + * + * Based on RAM init sequence by Piotr Dymacz + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include +#include +#include + +DECLARE_GLOBAL_DATA_PTR; + +enum { + AR934X_SDRAM = 0, + AR934X_DDR1, + AR934X_DDR2, +}; + +struct ar934x_mem_config { + u32 config1; + u32 config2; + u32 mode; + u32 extmode; + u32 tap; +}; + +static const struct ar934x_mem_config ar934x_mem_config[] = { + [AR934X_SDRAM] = { 0x7fbe8cd0, 0x959f66a8, 0x33, 0, 0x1f1f }, + [AR934X_DDR1] = { 0x7fd48cd0, 0x99d0e6a8, 0x33, 0, 0x14 }, + [AR934X_DDR2] = { 0xc7d48cd0, 0x9dd0e6a8, 0x33, 0, 0x10012 }, +}; + +void ar934x_ddr_init(const u16 cpu_mhz, const u16 ddr_mhz, const u16 ahb_mhz) +{ + void __iomem *ddr_regs; + const struct ar934x_mem_config *memcfg; + int memtype; + u32 reg, cycle, ctl; + + ddr_regs = map_physmem(AR71XX_DDR_CTRL_BASE, AR71XX_DDR_CTRL_SIZE, + MAP_NOCACHE); + + reg = get_bootstrap(); + if (reg & AR934X_BOOTSTRAP_SDRAM_DISABLED) { /* DDR */ + if (reg & AR934X_BOOTSTRAP_DDR1) { /* DDR 1 */ + memtype = AR934X_DDR1; + cycle = 0xffff; + } else { /* DDR 2 */ + memtype = AR934X_DDR2; + if (gd->arch.rev) { + ctl = BIT(6); /* Undocumented bit :-( */ + if (reg & BIT(3)) + cycle = 0xff; + else + cycle = 0xffff; + } else { + /* Force DDR2/x16 configuratio on old chips. */ + ctl = 0; + cycle = 0xffff; /* DDR2 16bit */ + } + + writel(0xe59, ddr_regs + AR934X_DDR_REG_DDR2_CONFIG); + udelay(100); + + writel(0x10, ddr_regs + AR71XX_DDR_REG_CONTROL); + udelay(10); + + writel(0x20, ddr_regs + AR71XX_DDR_REG_CONTROL); + udelay(10); + + writel(ctl, ddr_regs + AR934X_DDR_REG_CTL_CONF); + udelay(10); + } + } else { /* SDRAM */ + memtype = AR934X_SDRAM; + cycle = 0xffffffff; + + writel(0x13b, ddr_regs + AR934X_DDR_REG_CTL_CONF); + udelay(100); + + /* Undocumented register */ + writel(0x13b, ddr_regs + 0x118); + udelay(100); + } + + memcfg = &ar934x_mem_config[memtype]; + + writel(memcfg->config1, ddr_regs + AR71XX_DDR_REG_CONFIG); + udelay(100); + + writel(memcfg->config2, ddr_regs + AR71XX_DDR_REG_CONFIG2); + udelay(100); + + writel(0x8, ddr_regs + AR71XX_DDR_REG_CONTROL); + udelay(10); + + writel(memcfg->mode | 0x100, ddr_regs + AR71XX_DDR_REG_MODE); + mdelay(1); + + writel(0x1, ddr_regs + AR71XX_DDR_REG_CONTROL); + udelay(10); + + if (memtype == AR934X_DDR2) { + writel(memcfg->mode | 0x100, ddr_regs + AR71XX_DDR_REG_EMR); + udelay(100); + + writel(0x2, ddr_regs + AR71XX_DDR_REG_CONTROL); + udelay(10); + } + + if (memtype != AR934X_SDRAM) + writel(0x402, ddr_regs + AR71XX_DDR_REG_EMR); + + udelay(100); + + writel(0x2, ddr_regs + AR71XX_DDR_REG_CONTROL); + udelay(10); + + writel(0x8, ddr_regs + AR71XX_DDR_REG_CONTROL); + udelay(10); + + writel(memcfg->mode, ddr_regs + AR71XX_DDR_REG_MODE); + udelay(100); + + writel(0x1, ddr_regs + AR71XX_DDR_REG_CONTROL); + udelay(10); + + writel(0x412c /* FIXME */, ddr_regs + AR71XX_DDR_REG_REFRESH); + udelay(100); + + writel(memcfg->tap, ddr_regs + AR71XX_DDR_REG_TAP_CTRL0); + writel(memcfg->tap, ddr_regs + AR71XX_DDR_REG_TAP_CTRL1); + + if (memtype != AR934X_SDRAM) { + if ((gd->arch.rev && (reg & BIT(3))) || !gd->arch.rev) { + writel(memcfg->tap, + ddr_regs + AR934X_DDR_REG_TAP_CTRL2); + writel(memcfg->tap, + ddr_regs + AR934X_DDR_REG_TAP_CTRL3); + } + } + + writel(cycle, ddr_regs + AR71XX_DDR_REG_RD_CYCLE); + udelay(100); + + writel(0x74444444, ddr_regs + AR934X_DDR_REG_BURST); + udelay(100); + + writel(0x222, ddr_regs + AR934X_DDR_REG_BURST2); + udelay(100); + + writel(0xfffff, ddr_regs + AR934X_DDR_REG_TIMEOUT_MAX); + udelay(100); +} + +void ddr_tap_tuning(void) +{ +} diff --git a/arch/mips/mach-ath79/include/mach/ar71xx_regs.h b/arch/mips/mach-ath79/include/mach/ar71xx_regs.h index a9630c081b..a8e51cb4cf 100644 --- a/arch/mips/mach-ath79/include/mach/ar71xx_regs.h +++ b/arch/mips/mach-ath79/include/mach/ar71xx_regs.h @@ -250,11 +250,22 @@ #define AR933X_DDR_REG_TIMEOUT_CNT 0x9c #define AR933X_DDR_REG_TIMEOUT_ADDR 0x9c +#define AR934X_DDR_REG_TAP_CTRL2 0x24 +#define AR934X_DDR_REG_TAP_CTRL3 0x28 #define AR934X_DDR_REG_FLUSH_GE0 0x9c #define AR934X_DDR_REG_FLUSH_GE1 0xa0 #define AR934X_DDR_REG_FLUSH_USB 0xa4 #define AR934X_DDR_REG_FLUSH_PCIE 0xa8 #define AR934X_DDR_REG_FLUSH_WMAC 0xac +#define AR934X_DDR_REG_FLUSH_SRC1 0xb0 +#define AR934X_DDR_REG_FLUSH_SRC2 0xb4 +#define AR934X_DDR_REG_DDR2_CONFIG 0xb8 +#define AR934X_DDR_REG_EMR2 0xbc +#define AR934X_DDR_REG_EMR3 0xc0 +#define AR934X_DDR_REG_BURST 0xc4 +#define AR934X_DDR_REG_BURST2 0xc8 +#define AR934X_DDR_REG_TIMEOUT_MAX 0xcc +#define AR934X_DDR_REG_CTL_CONF 0x108 #define QCA953X_DDR_REG_FLUSH_GE0 0x9c #define QCA953X_DDR_REG_FLUSH_GE1 0xa0 @@ -341,6 +352,8 @@ #define AR934X_PLL_CPU_DDR_CLK_CTRL_REG 0x08 #define AR934X_PLL_SWITCH_CLOCK_CONTROL_REG 0x24 #define AR934X_PLL_ETH_XMII_CONTROL_REG 0x2c +#define AR934X_PLL_DDR_DIT_FRAC_REG 0x44 +#define AR934X_PLL_CPU_DIT_FRAC_REG 0x48 #define AR934X_PLL_CPU_CONFIG_NFRAC_SHIFT 0 #define AR934X_PLL_CPU_CONFIG_NFRAC_MASK 0x3f @@ -348,8 +361,12 @@ #define AR934X_PLL_CPU_CONFIG_NINT_MASK 0x3f #define AR934X_PLL_CPU_CONFIG_REFDIV_SHIFT 12 #define AR934X_PLL_CPU_CONFIG_REFDIV_MASK 0x1f +#define AR934X_PLL_CPU_CONFIG_RANGE_SHIFT 17 +#define AR934X_PLL_CPU_CONFIG_RANGE_MASK 0x3 #define AR934X_PLL_CPU_CONFIG_OUTDIV_SHIFT 19 #define AR934X_PLL_CPU_CONFIG_OUTDIV_MASK 0x3 +#define AR934X_PLL_CPU_CONFIG_PLLPWD BIT(30) +#define AR934X_PLL_CPU_CONFIG_UPDATING BIT(31) #define AR934X_PLL_DDR_CONFIG_NFRAC_SHIFT 0 #define AR934X_PLL_DDR_CONFIG_NFRAC_MASK 0x3ff @@ -357,8 +374,12 @@ #define AR934X_PLL_DDR_CONFIG_NINT_MASK 0x3f #define AR934X_PLL_DDR_CONFIG_REFDIV_SHIFT 16 #define AR934X_PLL_DDR_CONFIG_REFDIV_MASK 0x1f +#define AR934X_PLL_DDR_CONFIG_RANGE_SHIFT 21 +#define AR934X_PLL_DDR_CONFIG_RANGE_MASK 0x3 #define AR934X_PLL_DDR_CONFIG_OUTDIV_SHIFT 23 #define AR934X_PLL_DDR_CONFIG_OUTDIV_MASK 0x7 +#define AR934X_PLL_DDR_CONFIG_PLLPWD BIT(30) +#define AR934X_PLL_DDR_CONFIG_UPDATING BIT(31) #define AR934X_PLL_CLK_CTRL_CPU_PLL_BYPASS BIT(2) #define AR934X_PLL_CLK_CTRL_DDR_PLL_BYPASS BIT(3) @@ -375,6 +396,26 @@ #define AR934X_PLL_SWITCH_CLK_CTRL_MDIO_CLK_SEL BIT(6) +#define AR934X_PLL_DDR_DIT_FRAC_MAX_SHIFT 0 +#define AR934X_PLL_DDR_DIT_FRAC_MAX_MASK 0x3ff +#define AR934X_PLL_DDR_DIT_FRAC_MIN_SHIFT 10 +#define AR934X_PLL_DDR_DIT_FRAC_MIN_MASK 0x3ff +#define AR934X_PLL_DDR_DIT_FRAC_STEP_SHIFT 20 +#define AR934X_PLL_DDR_DIT_FRAC_STEP_MASK 0x3f +#define AR934X_PLL_DDR_DIT_UPD_CNT_SHIFT 27 +#define AR934X_PLL_DDR_DIT_UPD_CNT_MASK 0x3f +#define AR934X_PLL_DDR_DIT_DITHER_EN BIT(31) + +#define AR934X_PLL_CPU_DIT_FRAC_MAX_SHIFT 0 +#define AR934X_PLL_CPU_DIT_FRAC_MAX_MASK 0x3f +#define AR934X_PLL_CPU_DIT_FRAC_MIN_SHIFT 6 +#define AR934X_PLL_CPU_DIT_FRAC_MIN_MASK 0x3f +#define AR934X_PLL_CPU_DIT_FRAC_STEP_SHIFT 12 +#define AR934X_PLL_CPU_DIT_FRAC_STEP_MASK 0x3f +#define AR934X_PLL_CPU_DIT_UPD_CNT_SHIFT 18 +#define AR934X_PLL_CPU_DIT_UPD_CNT_MASK 0x3f +#define AR934X_PLL_CPU_DIT_DITHER_EN BIT(31) + #define QCA953X_PLL_CPU_CONFIG_REG 0x00 #define QCA953X_PLL_DDR_CONFIG_REG 0x04 #define QCA953X_PLL_CLK_CTRL_REG 0x08 @@ -1081,10 +1122,12 @@ #define AR934X_SRIF_CPU_DPLL1_REG 0x1c0 #define AR934X_SRIF_CPU_DPLL2_REG 0x1c4 #define AR934X_SRIF_CPU_DPLL3_REG 0x1c8 +#define AR934X_SRIF_CPU_DPLL4_REG 0x1cc #define AR934X_SRIF_DDR_DPLL1_REG 0x240 #define AR934X_SRIF_DDR_DPLL2_REG 0x244 #define AR934X_SRIF_DDR_DPLL3_REG 0x248 +#define AR934X_SRIF_DDR_DPLL4_REG 0x24c #define AR934X_SRIF_DPLL1_REFDIV_SHIFT 27 #define AR934X_SRIF_DPLL1_REFDIV_MASK 0x1f diff --git a/arch/mips/mach-ath79/include/mach/ath79.h b/arch/mips/mach-ath79/include/mach/ath79.h index 2c6c118176..17af08223f 100644 --- a/arch/mips/mach-ath79/include/mach/ath79.h +++ b/arch/mips/mach-ath79/include/mach/ath79.h @@ -143,4 +143,7 @@ static inline int soc_is_qca956x(void) int ath79_eth_reset(void); int ath79_usb_reset(void); +void ar934x_pll_init(const u16 cpu_mhz, const u16 ddr_mhz, const u16 ahb_mhz); +void ar934x_ddr_init(const u16 cpu_mhz, const u16 ddr_mhz, const u16 ahb_mhz); + #endif /* __ASM_MACH_ATH79_H */ From 400df3099896bdd43dd72dbb5d3930cf573d14f0 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Fri, 6 May 2016 20:10:41 +0200 Subject: [PATCH 145/162] mips: ath79: Add support for TPLink WDR4300 Add support for the TPLink WDR4300 router, which is based on the AR9344 MIPS 74Kc CPU and has 128 MiB of RAM. The USB is supported on this system as well. Signed-off-by: Marek Vasut Cc: Daniel Schwierzeck Cc: Wills Wang --- arch/mips/dts/Makefile | 1 + arch/mips/dts/tplink_wdr4300.dts | 53 ++++++++++++++++++ arch/mips/mach-ath79/Kconfig | 5 ++ board/tplink/wdr4300/Kconfig | 15 ++++++ board/tplink/wdr4300/MAINTAINERS | 6 +++ board/tplink/wdr4300/Makefile | 5 ++ board/tplink/wdr4300/wdr4300.c | 74 +++++++++++++++++++++++++ configs/tplink_wdr4300_defconfig | 43 +++++++++++++++ include/configs/tplink_wdr4300.h | 93 ++++++++++++++++++++++++++++++++ 9 files changed, 295 insertions(+) create mode 100644 arch/mips/dts/tplink_wdr4300.dts create mode 100644 board/tplink/wdr4300/Kconfig create mode 100644 board/tplink/wdr4300/MAINTAINERS create mode 100644 board/tplink/wdr4300/Makefile create mode 100644 board/tplink/wdr4300/wdr4300.c create mode 100644 configs/tplink_wdr4300_defconfig create mode 100644 include/configs/tplink_wdr4300.h diff --git a/arch/mips/dts/Makefile b/arch/mips/dts/Makefile index bd87ead972..a94b745550 100644 --- a/arch/mips/dts/Makefile +++ b/arch/mips/dts/Makefile @@ -5,6 +5,7 @@ dtb-$(CONFIG_TARGET_AP121) += ap121.dtb dtb-$(CONFIG_TARGET_AP143) += ap143.dtb dtb-$(CONFIG_TARGET_PIC32MZDASK) += pic32mzda_sk.dtb +dtb-$(CONFIG_BOARD_TPLINK_WDR4300) += tplink_wdr4300.dtb targets += $(dtb-y) diff --git a/arch/mips/dts/tplink_wdr4300.dts b/arch/mips/dts/tplink_wdr4300.dts new file mode 100644 index 0000000000..cfda4df72b --- /dev/null +++ b/arch/mips/dts/tplink_wdr4300.dts @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2016 Marek Vasut + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +/dts-v1/; +#include "ar934x.dtsi" + +/ { + model = "TP-Link WDR4300 Board"; + compatible = "tplink,wdr4300", "qca,ar934x"; + + aliases { + serial0 = &uart0; + spi0 = &spi0; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; +}; + +&ehci0 { + status = "okay"; +}; + +&gmac0 { + phy-mode = "rgmii"; + status = "okay"; +}; + +&spi0 { + spi-max-frequency = <25000000>; + status = "okay"; + spi-flash@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "spi-flash"; + memory-map = <0x1e000000 0x00800000>; + spi-max-frequency = <25000000>; + reg = <0>; + }; +}; + +&uart0 { + clock-frequency = <40000000>; + status = "okay"; +}; + +&xtal { + clock-frequency = <40000000>; +}; diff --git a/arch/mips/mach-ath79/Kconfig b/arch/mips/mach-ath79/Kconfig index 527960f4eb..7d483aa8dc 100644 --- a/arch/mips/mach-ath79/Kconfig +++ b/arch/mips/mach-ath79/Kconfig @@ -42,9 +42,14 @@ config TARGET_AP143 bool "AP143 Reference Board" select SOC_QCA953X +config BOARD_TPLINK_WDR4300 + bool "TP-Link WDR4300 Board" + select SOC_AR934X + endchoice source "board/qca/ap121/Kconfig" source "board/qca/ap143/Kconfig" +source "board/tplink/wdr4300/Kconfig" endmenu diff --git a/board/tplink/wdr4300/Kconfig b/board/tplink/wdr4300/Kconfig new file mode 100644 index 0000000000..902abf560d --- /dev/null +++ b/board/tplink/wdr4300/Kconfig @@ -0,0 +1,15 @@ +if BOARD_TPLINK_WDR4300 + +config SYS_VENDOR + default "tplink" + +config SYS_SOC + default "ath79" + +config SYS_BOARD + default "wdr4300" + +config SYS_CONFIG_NAME + default "tplink_wdr4300" + +endif diff --git a/board/tplink/wdr4300/MAINTAINERS b/board/tplink/wdr4300/MAINTAINERS new file mode 100644 index 0000000000..db239c291a --- /dev/null +++ b/board/tplink/wdr4300/MAINTAINERS @@ -0,0 +1,6 @@ +TPLINK_WDR4300 BOARD +M: Marek Vasut +S: Maintained +F: board/tplink/wdr4300/ +F: include/configs/tplink_wdr4300.h +F: configs/tplink_wdr4300_defconfig diff --git a/board/tplink/wdr4300/Makefile b/board/tplink/wdr4300/Makefile new file mode 100644 index 0000000000..4f0c296628 --- /dev/null +++ b/board/tplink/wdr4300/Makefile @@ -0,0 +1,5 @@ +# +# SPDX-License-Identifier: GPL-2.0+ +# + +obj-y = wdr4300.o diff --git a/board/tplink/wdr4300/wdr4300.c b/board/tplink/wdr4300/wdr4300.c new file mode 100644 index 0000000000..6e070fd558 --- /dev/null +++ b/board/tplink/wdr4300/wdr4300.c @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2016 Marek Vasut + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +DECLARE_GLOBAL_DATA_PTR; + +#ifdef CONFIG_USB +static void wdr4300_usb_start(void) +{ + void __iomem *gpio_regs = map_physmem(AR71XX_GPIO_BASE, + AR71XX_GPIO_SIZE, MAP_NOCACHE); + if (!gpio_regs) + return; + + /* Power up the USB HUB. */ + clrbits_be32(gpio_regs + AR71XX_GPIO_REG_OE, BIT(21) | BIT(22)); + writel(BIT(21) | BIT(22), gpio_regs + AR71XX_GPIO_REG_SET); + mdelay(1); + + ath79_usb_reset(); +} +#else +static inline void wdr4300_usb_start(void) {} +#endif + +#ifdef CONFIG_BOARD_EARLY_INIT_F +int board_early_init_f(void) +{ + void __iomem *regs; + + regs = map_physmem(AR71XX_GPIO_BASE, AR71XX_GPIO_SIZE, + MAP_NOCACHE); + + /* Assure JTAG is not disconnected. */ + writel(0x40, regs + AR934X_GPIO_REG_FUNC); + + /* Configure default GPIO input/output regs. */ + writel(0x3031b, regs + AR71XX_GPIO_REG_OE); + writel(0x0f804, regs + AR71XX_GPIO_REG_OUT); + + /* Configure pin multiplexing. */ + writel(0x00000000, regs + AR934X_GPIO_REG_OUT_FUNC0); + writel(0x0b0a0980, regs + AR934X_GPIO_REG_OUT_FUNC1); + writel(0x00180000, regs + AR934X_GPIO_REG_OUT_FUNC2); + writel(0x00000000, regs + AR934X_GPIO_REG_OUT_FUNC3); + writel(0x0000004d, regs + AR934X_GPIO_REG_OUT_FUNC4); + writel(0x00000000, regs + AR934X_GPIO_REG_OUT_FUNC5); + +#ifdef CONFIG_DEBUG_UART + debug_uart_init(); +#endif + +#ifndef CONFIG_SKIP_LOWLEVEL_INIT + ar934x_pll_init(560, 480, 240); + ar934x_ddr_init(560, 480, 240); +#endif + + wdr4300_usb_start(); + ath79_eth_reset(); + + return 0; +} +#endif diff --git a/configs/tplink_wdr4300_defconfig b/configs/tplink_wdr4300_defconfig new file mode 100644 index 0000000000..b1af2f6f35 --- /dev/null +++ b/configs/tplink_wdr4300_defconfig @@ -0,0 +1,43 @@ +CONFIG_MIPS=y +CONFIG_ARCH_ATH79=y +CONFIG_BOARD_TPLINK_WDR4300=y +CONFIG_SYS_MALLOC_F_LEN=0x2000 +CONFIG_SYS_NS16550=y +CONFIG_DM_SERIAL=y +CONFIG_DEFAULT_DEVICE_TREE="tplink_wdr4300" +# CONFIG_CMD_ELF is not set +# CONFIG_CMD_IMLS is not set +# CONFIG_CMD_XIMG is not set +# CONFIG_CMD_FLASH is not set +# CONFIG_CMD_FPGA is not set +CONFIG_CMD_NET=y +CONFIG_CMD_NFS=y +CONFIG_CMD_DHCP=y +CONFIG_CMD_PING=y +CONFIG_NET_RANDOM_ETHADDR=y +CONFIG_DM_ETH=y +CONFIG_AG7XXX=y +CONFIG_CLK=y +CONFIG_CMD_USB=y +CONFIG_USB=y +CONFIG_DM_USB=y +CONFIG_USB_EHCI_HCD=y +CONFIG_USB_EHCI_GENERIC=y +CONFIG_USB_STORAGE=y +CONFIG_ATH79_SPI=y +CONFIG_DM_SPI=y +CONFIG_DM_SPI_FLASH=y +CONFIG_CMD_SF=y +CONFIG_CMD_SPI=y +CONFIG_SPI_FLASH=y +CONFIG_SPI_FLASH_ATMEL=y +CONFIG_SPI_FLASH_EON=y +CONFIG_SPI_FLASH_GIGADEVICE=y +CONFIG_SPI_FLASH_MACRONIX=y +CONFIG_SPI_FLASH_SPANSION=y +CONFIG_SPI_FLASH_STMICRO=y +CONFIG_SPI_FLASH_SST=y +CONFIG_SPI_FLASH_WINBOND=y +CONFIG_SPI_FLASH_DATAFLASH=y +CONFIG_SPI_FLASH_MTD=y +CONFIG_PINCTRL=y diff --git a/include/configs/tplink_wdr4300.h b/include/configs/tplink_wdr4300.h new file mode 100644 index 0000000000..2b9e92ed2b --- /dev/null +++ b/include/configs/tplink_wdr4300.h @@ -0,0 +1,93 @@ +/* + * Copyright (C) 2016 Marek Vasut + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef __CONFIG_H +#define __CONFIG_H + +#define CONFIG_SYS_TEXT_BASE 0xa1000000 + +#define CONFIG_DISPLAY_CPUINFO +#define CONFIG_DISPLAY_BOARDINFO +#define CONFIG_BOARD_EARLY_INIT_F + +#define CONFIG_SYS_HZ 1000 +#define CONFIG_SYS_MHZ 280 +#define CONFIG_SYS_MIPS_TIMER_FREQ (CONFIG_SYS_MHZ * 1000000) + +/* Cache Configuration */ +#define CONFIG_SYS_DCACHE_SIZE 0x8000 +#define CONFIG_SYS_ICACHE_SIZE 0x10000 +#define CONFIG_SYS_CACHELINE_SIZE 32 + +#define CONFIG_SYS_MONITOR_BASE CONFIG_SYS_TEXT_BASE + +#define CONFIG_SYS_MALLOC_LEN 0x40000 +#define CONFIG_SYS_BOOTPARAMS_LEN 0x20000 + +#define CONFIG_SYS_SDRAM_BASE 0xa0000000 +#define CONFIG_SYS_LOAD_ADDR 0xa1000000 +#define CONFIG_LOADADDR CONFIG_SYS_LOAD_ADDR + +#define CONFIG_SYS_NO_FLASH + +#define CONFIG_SYS_INIT_RAM_ADDR 0xbd000000 +#define CONFIG_SYS_INIT_RAM_SIZE 0x8000 +#define CONFIG_SYS_INIT_SP_ADDR \ + (CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_INIT_RAM_SIZE) + +/* + * Serial Port + */ +#define CONFIG_SYS_NS16550_CLK 40000000 +#define CONFIG_BAUDRATE 115200 +#define CONFIG_SYS_BAUDRATE_TABLE \ + {9600, 19200, 38400, 57600, 115200} + +#define CONFIG_BOOTDELAY 3 +#define CONFIG_BOOTARGS \ + "console=ttyS0,115200 root=/dev/mtdblock2 rootfstype=squashfs" +#define CONFIG_BOOTCOMMAND \ + "dhcp 192.168.1.1:wdr4300.fit && bootm $loadaddr" +#define CONFIG_LZMA + +#define CONFIG_ENV_IS_NOWHERE +#define CONFIG_ENV_SIZE 0x10000 + +/* + * Command + */ +/* Miscellaneous configurable options */ +#define CONFIG_SYS_LONGHELP +#define CONFIG_SYS_CBSIZE 1024 /* Console I/O buffer size */ +#define CONFIG_SYS_MAXARGS 32 /* Max number of command args */ +#define CONFIG_SYS_BARGSIZE CONFIG_SYS_CBSIZE + /* Boot argument buffer size */ +#define CONFIG_VERSION_VARIABLE /* U-BOOT version */ +#define CONFIG_AUTO_COMPLETE /* Command auto complete */ +#define CONFIG_CMDLINE_EDITING /* Command history etc */ +#define CONFIG_SYS_HUSH_PARSER +#define CONFIG_SYS_PROMPT_HUSH_PS2 "> " + +/* USB, USB storage, USB ethernet */ +#define CONFIG_EHCI_MMIO_BIG_ENDIAN +#define CONFIG_EHCI_DESC_BIG_ENDIAN +#define CONFIG_EHCI_IS_TDI + +#define CONFIG_DOS_PARTITION + +/* + * Diagnostics + */ +#define CONFIG_SYS_MEMTEST_START 0x80100000 +#define CONFIG_SYS_MEMTEST_END 0x83f00000 +#define CONFIG_CMD_MEMTEST + +#define CONFIG_USE_PRIVATE_LIBGCC + +#define CONFIG_CMD_MII +#define CONFIG_PHY_GIGE + +#endif /* __CONFIG_H */ From 9f8ac82452d8bb5eccc38a0c3c0a8f82e1774452 Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Mon, 16 May 2016 10:52:10 +0100 Subject: [PATCH 146/162] MIPS: Use unchecked immediate addition/subtraction In MIPS assembly there have historically been 2 variants of immediate addition - the standard "addi" which traps if an overflow occurs, and the unchecked "addiu" which does not trap on overflow. In release 6 of the MIPS architecture the trapping variants of immediate addition & subtraction have been removed. In preparation for supporting MIPSr6, stop using the trapping instructions from assembly & switch to their unchecked variants. Signed-off-by: Paul Burton --- arch/mips/cpu/start.S | 22 ++++++++++++---------- arch/mips/lib/cache_init.S | 2 +- 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/arch/mips/cpu/start.S b/arch/mips/cpu/start.S index 1b56ca350a..fc6dd66aa6 100644 --- a/arch/mips/cpu/start.S +++ b/arch/mips/cpu/start.S @@ -164,12 +164,14 @@ reset: li t0, -16 PTR_LI t1, CONFIG_SYS_INIT_SP_ADDR and sp, t1, t0 # force 16 byte alignment - PTR_SUB sp, sp, GD_SIZE # reserve space for gd + PTR_SUBU \ + sp, sp, GD_SIZE # reserve space for gd and sp, sp, t0 # force 16 byte alignment move k0, sp # save gd pointer #ifdef CONFIG_SYS_MALLOC_F_LEN li t2, CONFIG_SYS_MALLOC_F_LEN - PTR_SUB sp, sp, t2 # reserve space for early malloc + PTR_SUBU \ + sp, sp, t2 # reserve space for early malloc and sp, sp, t0 # force 16 byte alignment #endif move fp, sp @@ -179,7 +181,7 @@ reset: 1: PTR_S zero, 0(t0) blt t0, t1, 1b - PTR_ADDI t0, PTRSIZE + PTR_ADDIU t0, PTRSIZE #ifdef CONFIG_SYS_MALLOC_F_LEN PTR_S sp, GD_MALLOC_BASE(k0) # gd->malloc_base offset @@ -237,7 +239,7 @@ ENTRY(relocate_code) move a0, s2 # a0 <-- destination address /* Jump to where we've relocated ourselves */ - PTR_ADDI t0, s2, in_ram - _start + PTR_ADDIU t0, s2, in_ram - _start jr t0 nop @@ -257,7 +259,7 @@ in_ram: PTR_L t3, -(1 * PTRSIZE)(t0) # t3 <-- num_got_entries PTR_L t8, -(2 * PTRSIZE)(t0) # t8 <-- _GLOBAL_OFFSET_TABLE_ PTR_ADD t8, s1 # t8 now holds relocated _G_O_T_ - PTR_ADDI t8, t8, 2 * PTRSIZE # skipping first two entries + PTR_ADDIU t8, t8, 2 * PTRSIZE # skipping first two entries PTR_LI t2, 2 1: PTR_L t1, 0(t8) @@ -265,16 +267,16 @@ in_ram: PTR_ADD t1, s1 PTR_S t1, 0(t8) 2: - PTR_ADDI t2, 1 + PTR_ADDIU t2, 1 blt t2, t3, 1b - PTR_ADDI t8, PTRSIZE + PTR_ADDIU t8, PTRSIZE /* Update dynamic relocations */ PTR_L t1, -(4 * PTRSIZE)(t0) # t1 <-- __rel_dyn_start PTR_L t2, -(5 * PTRSIZE)(t0) # t2 <-- __rel_dyn_end b 2f # skip first reserved entry - PTR_ADDI t1, 2 * PTRSIZE + PTR_ADDIU t1, 2 * PTRSIZE 1: lw t8, -4(t1) # t8 <-- relocation info @@ -293,7 +295,7 @@ in_ram: 2: blt t1, t2, 1b - PTR_ADDI t1, 2 * PTRSIZE # each rel.dyn entry is 2*PTRSIZE bytes + PTR_ADDIU t1, 2 * PTRSIZE # each rel.dyn entry is 2*PTRSIZE bytes /* * Clear BSS @@ -307,7 +309,7 @@ in_ram: 1: PTR_S zero, 0(t1) blt t1, t2, 1b - PTR_ADDI t1, PTRSIZE + PTR_ADDIU t1, PTRSIZE move a0, s0 # a0 <-- gd move a1, s2 diff --git a/arch/mips/lib/cache_init.S b/arch/mips/lib/cache_init.S index 14cc2c49fd..08b7c3af52 100644 --- a/arch/mips/lib/cache_init.S +++ b/arch/mips/lib/cache_init.S @@ -64,7 +64,7 @@ /* detect associativity */ srl \sz, $1, \off + MIPS_CONF1_DA_SHF - MIPS_CONF1_DA_SHF andi \sz, \sz, (MIPS_CONF1_DA >> MIPS_CONF1_DA_SHF) - addi \sz, \sz, 1 + addiu \sz, \sz, 1 /* sz *= line_sz */ mul \sz, \sz, \line_sz From 20286cdff766d64dc718a9d855b049580dfeb3cc Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Mon, 16 May 2016 10:52:11 +0100 Subject: [PATCH 147/162] MIPS: Simplify CONFIG_SYS_CPU values Rather than having the values for CONFIG_SYS_CPU depend upon each architecture revision, have them depend upon the more general CONFIG_CPU_MIPS32 & CONFIG_CPU_MIPS64 which in turn depend upon the architecture revisions. This is done in preparation for adding MIPSr6 support, which would otherwise need to introduce new cases here. Signed-off-by: Paul Burton --- arch/mips/Kconfig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 188aaba92f..6acd1f4a79 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -5,8 +5,8 @@ config SYS_ARCH default "mips" config SYS_CPU - default "mips32" if CPU_MIPS32_R1 || CPU_MIPS32_R2 - default "mips64" if CPU_MIPS64_R1 || CPU_MIPS64_R2 + default "mips32" if CPU_MIPS32 + default "mips64" if CPU_MIPS64 choice prompt "Target select" From c52ebea1ccb6f8cdd0b1d883056d215c715a5920 Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Mon, 16 May 2016 10:52:12 +0100 Subject: [PATCH 148/162] MIPS: Support for targetting MIPSr6 Add support for targetting MIPS32r6 & MIPS64r6 systems, in the same way that we currently select release 1 or release 2 targets. MIPSr6 is not entirely backwards compatible with earlier releases of the architecture. Some instructions are encoded differently, some are removed, some are reused, so it is not practical to run U-Boot built for earlier revisions on a MIPSr6 system. Update their Kconfig help text to reflect that. Signed-off-by: Paul Burton --- arch/mips/Kconfig | 34 ++++++++++++++++++++++++++++------ arch/mips/Makefile | 2 ++ 2 files changed, 30 insertions(+), 6 deletions(-) diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 6acd1f4a79..994168c270 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -104,7 +104,7 @@ config CPU_MIPS32_R1 depends on SUPPORTS_CPU_MIPS32_R1 select 32BIT help - Choose this option to build an U-Boot for release 1 or later of the + Choose this option to build an U-Boot for release 1 through 5 of the MIPS32 architecture. config CPU_MIPS32_R2 @@ -112,7 +112,15 @@ config CPU_MIPS32_R2 depends on SUPPORTS_CPU_MIPS32_R2 select 32BIT help - Choose this option to build an U-Boot for release 2 or later of the + Choose this option to build an U-Boot for release 2 through 5 of the + MIPS32 architecture. + +config CPU_MIPS32_R6 + bool "MIPS32 Release 6" + depends on SUPPORTS_CPU_MIPS32_R6 + select 32BIT + help + Choose this option to build an U-Boot for release 6 or later of the MIPS32 architecture. config CPU_MIPS64_R1 @@ -120,7 +128,7 @@ config CPU_MIPS64_R1 depends on SUPPORTS_CPU_MIPS64_R1 select 64BIT help - Choose this option to build a kernel for release 1 or later of the + Choose this option to build a kernel for release 1 through 5 of the MIPS64 architecture. config CPU_MIPS64_R2 @@ -128,7 +136,15 @@ config CPU_MIPS64_R2 depends on SUPPORTS_CPU_MIPS64_R2 select 64BIT help - Choose this option to build a kernel for release 2 or later of the + Choose this option to build a kernel for release 2 through 5 of the + MIPS64 architecture. + +config CPU_MIPS64_R6 + bool "MIPS64 Release 6" + depends on SUPPORTS_CPU_MIPS64_R6 + select 64BIT + help + Choose this option to build a kernel for release 6 or later of the MIPS64 architecture. endchoice @@ -175,19 +191,25 @@ config SUPPORTS_CPU_MIPS32_R1 config SUPPORTS_CPU_MIPS32_R2 bool +config SUPPORTS_CPU_MIPS32_R6 + bool + config SUPPORTS_CPU_MIPS64_R1 bool config SUPPORTS_CPU_MIPS64_R2 bool +config SUPPORTS_CPU_MIPS64_R6 + bool + config CPU_MIPS32 bool - default y if CPU_MIPS32_R1 || CPU_MIPS32_R2 + default y if CPU_MIPS32_R1 || CPU_MIPS32_R2 || CPU_MIPS32_R6 config CPU_MIPS64 bool - default y if CPU_MIPS64_R1 || CPU_MIPS64_R2 + default y if CPU_MIPS64_R1 || CPU_MIPS64_R2 || CPU_MIPS64_R6 config MIPS_TUNE_4KC bool diff --git a/arch/mips/Makefile b/arch/mips/Makefile index 94f7e16e41..655a493382 100644 --- a/arch/mips/Makefile +++ b/arch/mips/Makefile @@ -19,8 +19,10 @@ PLATFORM_CPPFLAGS += $(patsubst %,-I$(srctree)/%include,$(machdirs)) # Optimize for MIPS architectures arch-$(CONFIG_CPU_MIPS32_R1) += -march=mips32 -Wa,-mips32 arch-$(CONFIG_CPU_MIPS32_R2) += -march=mips32r2 -Wa,-mips32r2 +arch-$(CONFIG_CPU_MIPS32_R6) += -march=mips32r6 -Wa,-mips32r6 arch-$(CONFIG_CPU_MIPS64_R1) += -march=mips64 -Wa,-mips64 arch-$(CONFIG_CPU_MIPS64_R2) += -march=mips64r2 -Wa,-mips64r2 +arch-$(CONFIG_CPU_MIPS64_R6) += -march=mips64r6 -Wa,-mips64r6 # Allow extra optimization for specific CPUs/SoCs tune-$(CONFIG_MIPS_TUNE_4KC) += -mtune=4kc From 4685d4e90d615adbca417826a7b777ec431e48a5 Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Mon, 16 May 2016 10:52:13 +0100 Subject: [PATCH 149/162] malta: Remove ".set mips32" directive We always build for a mips32 or higher ISA, so this ".set mips32" directive is redundant. Once MIPSr6 support is added it will become harmful since some instruction encodings change & this directive will cause the older encodings to be incorrectly emitted instead of the appropriate ones for the build. In preparation for supporting MIPSr6, remove this redundant directive. Signed-off-by: Paul Burton --- board/imgtec/malta/lowlevel_init.S | 1 - 1 file changed, 1 deletion(-) diff --git a/board/imgtec/malta/lowlevel_init.S b/board/imgtec/malta/lowlevel_init.S index ae09c27d07..534db1d832 100644 --- a/board/imgtec/malta/lowlevel_init.S +++ b/board/imgtec/malta/lowlevel_init.S @@ -24,7 +24,6 @@ .text .set noreorder - .set mips32 .globl lowlevel_init lowlevel_init: From 40ba13c98627055465709acd67872e381b42f928 Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Mon, 16 May 2016 10:52:14 +0100 Subject: [PATCH 150/162] malta: Support MIPS32r6 configurations Both real Malta boards & QEMU's Malta emulation can feature MIPS32r6 CPUs. Allow building U-Boot for such systems by selecting CONFIG_SUPPORTS_CPU_MIPS32_R6 for Malta. Signed-off-by: Paul Burton --- arch/mips/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 994168c270..dc34c18258 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -28,6 +28,7 @@ config TARGET_MALTA select SUPPORTS_LITTLE_ENDIAN select SUPPORTS_CPU_MIPS32_R1 select SUPPORTS_CPU_MIPS32_R2 + select SUPPORTS_CPU_MIPS32_R6 select SWAP_IO_SPACE select MIPS_L1_CACHE_SHIFT_6 From e7c2729bb358064ef7baf6081e6a47cf3f878e5c Mon Sep 17 00:00:00 2001 From: Nikita Kiryanov Date: Sat, 16 Apr 2016 17:55:12 +0300 Subject: [PATCH 151/162] eeprom: use eeprom_execute_command for all eeprom functions Update eeprom_execute_command() and related code to accommodate both layout aware and layout unaware functions. No functional changes. Cc: Heiko Schocher Cc: Marek Vasut Cc: Simon Glass Cc: Igor Grinberg Cc: Tom Rini Signed-off-by: Nikita Kiryanov [trini: Make eeprom_execute_command have ulong for i2c_addr] Signed-off-by: Tom Rini --- cmd/eeprom.c | 61 ++++++++++++++++++++++++++++++++++------------------ 1 file changed, 40 insertions(+), 21 deletions(-) diff --git a/cmd/eeprom.c b/cmd/eeprom.c index 54bf06ceb3..0f2a9f763f 100644 --- a/cmd/eeprom.c +++ b/cmd/eeprom.c @@ -24,6 +24,7 @@ #include #include #include +#include #ifndef CONFIG_SYS_I2C_SPEED #define CONFIG_SYS_I2C_SPEED 50000 @@ -258,7 +259,6 @@ static int parse_i2c_bus_addr(int *i2c_bus, ulong *i2c_addr, int argc, } #ifdef CONFIG_CMD_EEPROM_LAYOUT -#include __weak int eeprom_parse_layout_version(char *str) { @@ -271,12 +271,17 @@ static unsigned char eeprom_buf[CONFIG_SYS_EEPROM_SIZE]; #define CONFIG_EEPROM_LAYOUT_HELP_STRING "" #endif +#endif + enum eeprom_action { + EEPROM_READ, + EEPROM_WRITE, EEPROM_PRINT, EEPROM_UPDATE, EEPROM_ACTION_INVALID, }; +#ifdef CONFIG_CMD_EEPROM_LAYOUT static enum eeprom_action parse_action(char *cmd) { if (!strncmp(cmd, "print", 5)) @@ -286,18 +291,40 @@ static enum eeprom_action parse_action(char *cmd) return EEPROM_ACTION_INVALID; } +#endif static int eeprom_execute_command(enum eeprom_action action, int i2c_bus, - int i2c_addr, int layout_ver, char *key, - char *value) + ulong i2c_addr, int layout_ver, char *key, + char *value, ulong addr, ulong off, ulong cnt) { - int rcode; + int rcode = 0; + const char *const fmt = + "\nEEPROM @0x%lX %s: addr %08lx off %04lx count %ld ... "; +#ifdef CONFIG_CMD_EEPROM_LAYOUT struct eeprom_layout layout; +#endif if (action == EEPROM_ACTION_INVALID) return CMD_RET_USAGE; eeprom_init(i2c_bus); + if (action == EEPROM_READ) { + printf(fmt, i2c_addr, "read", addr, off, cnt); + + rcode = eeprom_read(i2c_addr, off, (uchar *)addr, cnt); + + puts("done\n"); + return rcode; + } else if (action == EEPROM_WRITE) { + printf(fmt, i2c_addr, "write", addr, off, cnt); + + rcode = eeprom_write(i2c_addr, off, (uchar *)addr, cnt); + + puts("done\n"); + return rcode; + } + +#ifdef CONFIG_CMD_EEPROM_LAYOUT rcode = eeprom_read(i2c_addr, 0, eeprom_buf, CONFIG_SYS_EEPROM_SIZE); if (rcode < 0) return rcode; @@ -313,10 +340,12 @@ static int eeprom_execute_command(enum eeprom_action action, int i2c_bus, layout.update(&layout, key, value); rcode = eeprom_write(i2c_addr, 0, layout.data, CONFIG_SYS_EEPROM_SIZE); +#endif return rcode; } +#ifdef CONFIG_CMD_EEPROM_LAYOUT #define NEXT_PARAM(argc, index) { (argc)--; (index)++; } static int do_eeprom_layout(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) @@ -369,15 +398,13 @@ static int do_eeprom_layout(cmd_tbl_t *cmdtp, int flag, int argc, done: return eeprom_execute_command(action, i2c_bus, i2c_addr, layout_ver, - field_name, field_value); + field_name, field_value, 0, 0, 0); } #endif static int do_eeprom(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { - const char *const fmt = - "\nEEPROM @0x%lX %s: addr %08lx off %04lx count %ld ... "; char * const *args = &argv[2]; int rcode; ulong dev_addr, addr, off, cnt; @@ -398,22 +425,14 @@ static int do_eeprom(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) off = simple_strtoul(*args++, NULL, 16); cnt = simple_strtoul(*args++, NULL, 16); - eeprom_init(bus_addr); - if (strcmp(argv[1], "read") == 0) { - printf(fmt, dev_addr, argv[1], addr, off, cnt); - - rcode = eeprom_read(dev_addr, off, (uchar *)addr, cnt); - - puts("done\n"); - return rcode; + return eeprom_execute_command(EEPROM_READ, bus_addr, dev_addr, + LAYOUT_VERSION_UNRECOGNIZED, + NULL, NULL, addr, off, cnt); } else if (strcmp(argv[1], "write") == 0) { - printf(fmt, dev_addr, argv[1], addr, off, cnt); - - rcode = eeprom_write(dev_addr, off, (uchar *)addr, cnt); - - puts("done\n"); - return rcode; + return eeprom_execute_command(EEPROM_WRITE, bus_addr, dev_addr, + LAYOUT_VERSION_UNRECOGNIZED, + NULL, NULL, addr, off, cnt); } return CMD_RET_USAGE; From 3dc9be82088f826dd7927bd1f947a838c9ef72b0 Mon Sep 17 00:00:00 2001 From: Nikita Kiryanov Date: Sat, 16 Apr 2016 17:55:13 +0300 Subject: [PATCH 152/162] eeprom: merge cmdline parsing of eeprom commands Merge the parsing of layout aware and layout unaware eeprom commands into one parsing function. With this change, layout aware commands now follow the eeprom read and eeprom write conventions of making i2c bus and i2c address parameters optional. Cc: Heiko Schocher Cc: Marek Vasut Cc: Simon Glass Cc: Igor Grinberg Cc: Tom Rini Signed-off-by: Nikita Kiryanov --- cmd/eeprom.c | 119 +++++++++++++++++++++++---------------------------- 1 file changed, 54 insertions(+), 65 deletions(-) diff --git a/cmd/eeprom.c b/cmd/eeprom.c index 0f2a9f763f..0a0e4a2c1c 100644 --- a/cmd/eeprom.c +++ b/cmd/eeprom.c @@ -281,17 +281,21 @@ enum eeprom_action { EEPROM_ACTION_INVALID, }; -#ifdef CONFIG_CMD_EEPROM_LAYOUT static enum eeprom_action parse_action(char *cmd) { + if (!strncmp(cmd, "read", 4)) + return EEPROM_READ; + if (!strncmp(cmd, "write", 5)) + return EEPROM_WRITE; +#ifdef CONFIG_CMD_EEPROM_LAYOUT if (!strncmp(cmd, "print", 5)) return EEPROM_PRINT; if (!strncmp(cmd, "update", 6)) return EEPROM_UPDATE; +#endif return EEPROM_ACTION_INVALID; } -#endif static int eeprom_execute_command(enum eeprom_action action, int i2c_bus, ulong i2c_addr, int layout_ver, char *key, @@ -345,14 +349,14 @@ static int eeprom_execute_command(enum eeprom_action action, int i2c_bus, return rcode; } -#ifdef CONFIG_CMD_EEPROM_LAYOUT #define NEXT_PARAM(argc, index) { (argc)--; (index)++; } -static int do_eeprom_layout(cmd_tbl_t *cmdtp, int flag, int argc, - char * const argv[]) +int do_eeprom(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { int layout_ver = LAYOUT_VERSION_AUTODETECT; enum eeprom_action action = EEPROM_ACTION_INVALID; - int i2c_bus = -1, i2c_addr = -1, index = 0; + int i2c_bus = -1, index = 0; + ulong i2c_addr = -1, addr = 0, cnt = 0, off = 0; + int ret; char *field_name = ""; char *field_value = ""; @@ -364,78 +368,63 @@ static int do_eeprom_layout(cmd_tbl_t *cmdtp, int flag, int argc, action = parse_action(argv[index]); NEXT_PARAM(argc, index); - if (argc <= 1) + if (action == EEPROM_ACTION_INVALID) return CMD_RET_USAGE; - if (!strcmp(argv[index], "-l")) { - NEXT_PARAM(argc, index); +#ifdef CONFIG_CMD_EEPROM_LAYOUT + if (action == EEPROM_PRINT || action == EEPROM_UPDATE) { + if (!strcmp(argv[index], "-l")) { + NEXT_PARAM(argc, index); + layout_ver = eeprom_parse_layout_version(argv[index]); + NEXT_PARAM(argc, index); + } + } +#endif - layout_ver = eeprom_parse_layout_version(argv[index]); - NEXT_PARAM(argc, index); + switch (action) { + case EEPROM_READ: + case EEPROM_WRITE: + ret = parse_i2c_bus_addr(&i2c_bus, &i2c_addr, argc, + argv + index, 3); + break; + case EEPROM_PRINT: + ret = parse_i2c_bus_addr(&i2c_bus, &i2c_addr, argc, + argv + index, 0); + break; + case EEPROM_UPDATE: + ret = parse_i2c_bus_addr(&i2c_bus, &i2c_addr, argc, + argv + index, 2); + break; + default: + /* Get compiler to stop whining */ + return CMD_RET_USAGE; } - if (argc <= 1) - return CMD_RET_USAGE; + if (ret == CMD_RET_USAGE) + return ret; - i2c_bus = parse_numeric_param(argv[index]); - NEXT_PARAM(argc, index); + while (ret--) + NEXT_PARAM(argc, index); - i2c_addr = parse_numeric_param(argv[index]); - NEXT_PARAM(argc, index); + if (action == EEPROM_READ || action == EEPROM_WRITE) { + addr = parse_numeric_param(argv[index]); + NEXT_PARAM(argc, index); + off = parse_numeric_param(argv[index]); + NEXT_PARAM(argc, index); + cnt = parse_numeric_param(argv[index]); + } - if (action == EEPROM_PRINT) - goto done; - - if (argc) { +#ifdef CONFIG_CMD_EEPROM_LAYOUT + if (action == EEPROM_UPDATE) { field_name = argv[index]; NEXT_PARAM(argc, index); - } - - if (argc) { field_value = argv[index]; NEXT_PARAM(argc, index); } +#endif -done: return eeprom_execute_command(action, i2c_bus, i2c_addr, layout_ver, - field_name, field_value, 0, 0, 0); -} - -#endif - -static int do_eeprom(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) -{ - char * const *args = &argv[2]; - int rcode; - ulong dev_addr, addr, off, cnt; - int bus_addr; - -#ifdef CONFIG_CMD_EEPROM_LAYOUT - if (argc >= 2) { - if (!strcmp(argv[1], "update") || !strcmp(argv[1], "print")) - return do_eeprom_layout(cmdtp, flag, argc, argv); - } -#endif - - rcode = parse_i2c_bus_addr(&bus_addr, &dev_addr, argc - 2, argv + 2, 3); - if (rcode == CMD_RET_USAGE) - return rcode; - - addr = simple_strtoul(*args++, NULL, 16); - off = simple_strtoul(*args++, NULL, 16); - cnt = simple_strtoul(*args++, NULL, 16); - - if (strcmp(argv[1], "read") == 0) { - return eeprom_execute_command(EEPROM_READ, bus_addr, dev_addr, - LAYOUT_VERSION_UNRECOGNIZED, - NULL, NULL, addr, off, cnt); - } else if (strcmp(argv[1], "write") == 0) { - return eeprom_execute_command(EEPROM_WRITE, bus_addr, dev_addr, - LAYOUT_VERSION_UNRECOGNIZED, - NULL, NULL, addr, off, cnt); - } - - return CMD_RET_USAGE; + field_name, field_value, addr, off, cnt); } U_BOOT_CMD( @@ -446,9 +435,9 @@ U_BOOT_CMD( " - read/write `cnt' bytes from `devaddr` EEPROM at offset `off'" #ifdef CONFIG_CMD_EEPROM_LAYOUT "\n" - "eeprom print [-l ] bus devaddr\n" + "eeprom print [-l ] \n" " - Print layout fields and their data in human readable format\n" - "eeprom update [-l ] bus devaddr \n" + "eeprom update [-l ] field_name field_value\n" " - Update a specific eeprom field with new data.\n" " The new data must be written in the same human readable format as shown by the print command.\n" "\n" From 83b6a43e6efdce32c7f824263ad40c86d03901f9 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Tue, 17 May 2016 10:51:44 -0300 Subject: [PATCH 153/162] pico-imx6ul: Select CONFIG_HUSH_PARSER option Select CONFIG_HUSH_PARSER option in order to fix the following problem: Unknown command 'if' - try 'help' Unknown command 'then' - try 'help' Unknown command 'else' - try 'help' Unknown command 'fi' - try 'help' Reported-by: Daiane Angolini Signed-off-by: Fabio Estevam Tested-by: Daiane Angolini --- configs/pico-imx6ul_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/configs/pico-imx6ul_defconfig b/configs/pico-imx6ul_defconfig index cc49dc976f..d46cd3bfa8 100644 --- a/configs/pico-imx6ul_defconfig +++ b/configs/pico-imx6ul_defconfig @@ -2,6 +2,7 @@ CONFIG_ARM=y CONFIG_ARCH_MX6=y CONFIG_TARGET_PICO_IMX6UL=y CONFIG_SYS_EXTRA_OPTIONS="IMX_CONFIG=board/technexion/pico-imx6ul/imximage.cfg" +CONFIG_HUSH_PARSER=y CONFIG_CMD_BOOTZ=y # CONFIG_CMD_IMLS is not set CONFIG_CMD_MEMTEST=y From 034eda867f47986e04be13087d193d2c12e3b9aa Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Mon, 25 Apr 2016 15:55:42 -0600 Subject: [PATCH 154/162] malloc: improve memalign fragmentation fix Commit 4f144a416469 "malloc: work around some memalign fragmentation issues" enhanced memalign() so that it can succeed in more cases where heap fragmentation is present. However, it did not solve as many cases as it could. This patch enhances the code to cover more cases. The alignment code works by allocating more space than the user requests, then adjusting the returned pointer to achieve alignment. In general, one must allocate "alignment" bytes more than the user requested in order to guarantee that alignment is possible. This is what the original code does. The previous enhancement attempted a second allocation if the padded allocation failed, and succeeded if that allocation just happened to be aligned; a fluke that happened often in practice. There are still cases where this could fail, yet where it is still possible to honor the user's allocation request. In particular, if the heap contains a free region that is large enough for the user's request, and for leading padding to ensure alignment, but has no or little space for any trailing padding. In this case, we can make a third(!) allocation attempt after calculating exactly the size of the leading padding required to achieve alignment, which is the minimal over-allocation needed for the overall memalign() operation to succeed if the third and second allocations end up at the same location. This patch isn't checkpatch-clean, since it conforms to the existing coding style in dlmalloc.c, which is different to the rest of U-Boot. Signed-off-by: Stephen Warren Reviewed-by: Tom Rini --- common/dlmalloc.c | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/common/dlmalloc.c b/common/dlmalloc.c index b09f5249a9..adc680e959 100644 --- a/common/dlmalloc.c +++ b/common/dlmalloc.c @@ -1909,6 +1909,7 @@ Void_t* mEMALIGn(alignment, bytes) size_t alignment; size_t bytes; * fulfill the user's request. */ if (m == NULL) { + size_t extra, extra2; /* * Use bytes not nb, since mALLOc internally calls request2size too, and * each call increases the size to allocate, to account for the header. @@ -1917,9 +1918,27 @@ Void_t* mEMALIGn(alignment, bytes) size_t alignment; size_t bytes; /* Aligned -> return it */ if ((((unsigned long)(m)) % alignment) == 0) return m; - /* Otherwise, fail */ + /* + * Otherwise, try again, requesting enough extra space to be able to + * acquire alignment. + */ fREe(m); - m = NULL; + /* Add in extra bytes to match misalignment of unexpanded allocation */ + extra = alignment - (((unsigned long)(m)) % alignment); + m = (char*)(mALLOc(bytes + extra)); + /* + * m might not be the same as before. Validate that the previous value of + * extra still works for the current value of m. + * If (!m), extra2=alignment so + */ + if (m) { + extra2 = alignment - (((unsigned long)(m)) % alignment); + if (extra2 > extra) { + fREe(m); + m = NULL; + } + } + /* Fall through to original NULL check and chunk splitting logic */ } if (m == NULL) return NULL; /* propagate failure */ From 8df81e17f81ba0542f6dbb7636db64fa56c12d8a Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 1 May 2016 13:55:37 -0600 Subject: [PATCH 155/162] image-fit: Don't display an error in fit_set_timestamp() This function returns an error code and its caller may be able to fix the error. For example fit_handle_file() expands the device tree to fit if there is a lack of space. In this case the caller does not want an error displayed. It is confusing, since it suggests that something is wrong, when it fact everything is fine. Drop the error. Signed-off-by: Simon Glass --- common/image-fit.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/common/image-fit.c b/common/image-fit.c index 25f8a1183d..c86b7c6b11 100644 --- a/common/image-fit.c +++ b/common/image-fit.c @@ -886,9 +886,9 @@ int fit_set_timestamp(void *fit, int noffset, time_t timestamp) ret = fdt_setprop(fit, noffset, FIT_TIMESTAMP_PROP, &t, sizeof(uint32_t)); if (ret) { - printf("Can't set '%s' property for '%s' node (%s)\n", - FIT_TIMESTAMP_PROP, fit_get_name(fit, noffset, NULL), - fdt_strerror(ret)); + debug("Can't set '%s' property for '%s' node (%s)\n", + FIT_TIMESTAMP_PROP, fit_get_name(fit, noffset, NULL), + fdt_strerror(ret)); return ret == -FDT_ERR_NOSPACE ? -ENOSPC : -1; } From bd6e14209445853f9024574b756bba3184bc215c Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 1 May 2016 13:55:38 -0600 Subject: [PATCH 156/162] mkimage: Add a quiet mode Some build systems want to be quiet unless there is a problem. At present mkimage displays quite a bit of information when generating a FIT file. Add a '-q' flag to silence this. Signed-off-by: Simon Glass Acked-by: Joe Hershberger --- tools/imagetool.c | 3 ++- tools/imagetool.h | 1 + tools/mkimage.c | 5 ++++- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/tools/imagetool.c b/tools/imagetool.c index 916ab964d5..08d191d9f8 100644 --- a/tools/imagetool.c +++ b/tools/imagetool.c @@ -51,7 +51,8 @@ int imagetool_verify_print_header( * successful */ if ((*curr)->print_header) { - (*curr)->print_header(ptr); + if (!params->quiet) + (*curr)->print_header(ptr); } else { fprintf(stderr, "%s: print_header undefined for %s\n", diff --git a/tools/imagetool.h b/tools/imagetool.h index 24f8f4b2f6..a3ed0f43d6 100644 --- a/tools/imagetool.h +++ b/tools/imagetool.h @@ -73,6 +73,7 @@ struct image_tool_params { struct content_info *content_head; /* List of files to include */ struct content_info *content_tail; bool external_data; /* Store data outside the FIT */ + bool quiet; /* Don't output text in normal operation */ }; /* diff --git a/tools/mkimage.c b/tools/mkimage.c index 93d1c16c7c..aefe22f19b 100644 --- a/tools/mkimage.c +++ b/tools/mkimage.c @@ -136,7 +136,7 @@ static void process_args(int argc, char **argv) int opt; while ((opt = getopt(argc, argv, - "a:A:b:cC:d:D:e:Ef:Fk:K:ln:O:rR:sT:vVx")) != -1) { + "a:A:b:cC:d:D:e:Ef:Fk:K:ln:O:rR:qsT:vVx")) != -1) { switch (opt) { case 'a': params.addr = strtoull(optarg, &ptr, 16); @@ -216,6 +216,9 @@ static void process_args(int argc, char **argv) if (params.os < 0) usage("Invalid operating system"); break; + case 'q': + params.quiet = 1; + break; case 'r': params.require_keys = 1; break; From 5adfa265793d2e41fd1619cafcd9cf4e18f80341 Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Wed, 4 May 2016 15:08:00 +0200 Subject: [PATCH 157/162] spl: fit: Print error message when FDT is not present When FDT is not present in the image user doesn't get any error what's wrong. Print error message if LIBCOMMON_SUPPORT is enabled. Signed-off-by: Michal Simek Seris-cc: uboot Reviewed-by: Tom Rini Reviewed-by: Simon Glass --- common/spl/spl_fit.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/common/spl/spl_fit.c b/common/spl/spl_fit.c index 1a5c0275a7..26842ba285 100644 --- a/common/spl/spl_fit.c +++ b/common/spl/spl_fit.c @@ -39,8 +39,13 @@ static int spl_fit_select_fdt(const void *fdt, int images, int *fdt_offsetp) node >= 0; node = fdt_next_subnode(fdt, node)) { name = fdt_getprop(fdt, node, "description", &len); - if (!name) + if (!name) { +#ifdef CONFIG_SPL_LIBCOMMON_SUPPORT + printf("%s: Missing FDT description in DTB\n", + __func__); +#endif return -EINVAL; + } if (board_fit_config_name_match(name)) continue; From c409bd015c295ba088af75b117d1dd6ebd8080ba Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Wed, 4 May 2016 15:14:11 +0200 Subject: [PATCH 158/162] spl: Setup default value for OF_LIST OF_LIST can't remain empty that's why setup it up to default DTB. If it is empty u-boot.img is created without FDT partition: For example: ./tools/mkimage -f auto -A arm -T firmware -C none -O u-boot -a 0x8000000 -e 0 -n "U-Boot 2016.05-rc3 ..." -E -b -d u-boot-nodtb.bin u-boot.img Can't set 'timestamp' property for '' node (FDT_ERR_NOSPACE) FIT description: Firmware image with one or more FDT blobs Created: Wed May 4 15:02:52 2016 Image 0 (firmware@1) Description: U-Boot 2016.05-rc3-00080-gff2e12ae22a8-dirty for zynqmp board Created: Wed May 4 15:02:52 2016 Type: Firmware Compression: uncompressed Data Size: unavailable Architecture: ARM Load Address: 0x08000000 Default Configuration: 'conf@1' Configuration 0 (conf@1) Description: unavailable Kernel: unavailable And then image like this doesn't contain description and link to FDT and can't boot. Signed-off-by: Michal Simek Reviewed-by: Tom Rini --- dts/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/dts/Kconfig b/dts/Kconfig index d585009353..c56c1299c0 100644 --- a/dts/Kconfig +++ b/dts/Kconfig @@ -62,6 +62,7 @@ config DEFAULT_DEVICE_TREE config OF_LIST string "List of device tree files to include for DT control" depends on SPL_LOAD_FIT + default DEFAULT_DEVICE_TREE help This option specifies a list of device tree files to use for DT control. These will be packaged into a FIT. At run-time, SPL will From c1420f8b2b0f3c833c024979495ab22db34a5dbe Mon Sep 17 00:00:00 2001 From: Tom Rini Date: Fri, 13 May 2016 10:54:04 -0400 Subject: [PATCH 159/162] kbuild: fixdep: Check fstat(2) return value Coverity has recently added a check that will find when we don't check the return code from fstat(2). Copy/paste the checking logic that print_deps() has with an appropriate re-wording of the perror() message. [ Linux commit : 46fe94ad18aa7ce6b3dad8c035fb538942020f2b ] Signed-off-by: Tom Rini Signed-off-by: Michal Marek --- scripts/basic/fixdep.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/scripts/basic/fixdep.c b/scripts/basic/fixdep.c index e8e8c7756d..9bd0de2490 100644 --- a/scripts/basic/fixdep.c +++ b/scripts/basic/fixdep.c @@ -296,7 +296,11 @@ static void do_config_file(const char *filename) perror(filename); exit(2); } - fstat(fd, &st); + if (fstat(fd, &st) < 0) { + fprintf(stderr, "fixdep: error fstat'ing config file: "); + perror(filename); + exit(2); + } if (st.st_size == 0) { close(fd); return; From 5f89a15e1630e9050c8b1b5307ccd800e4596ce5 Mon Sep 17 00:00:00 2001 From: Martin Hejnfelt Date: Thu, 19 May 2016 09:11:58 +0200 Subject: [PATCH 160/162] omap3: Fix SPI registers on am33xx and am43xx When the base registers are read from device tree the base is not 0x48030100 as the driver expects, but 0x48030000, resulting in non functioning SPI. To deal with this, use same idea as how this is done in the linux kernel (drivers/spi/spi-omap2-mcspi.c) and add a structure with a field that is used to shift the registers on these systems. v2: Fixed commit subject line to correct cpu Signed-off-by: Martin Hejnfelt --- drivers/spi/omap3_spi.c | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/drivers/spi/omap3_spi.c b/drivers/spi/omap3_spi.c index 2fe34c9a14..60e9d6e825 100644 --- a/drivers/spi/omap3_spi.c +++ b/drivers/spi/omap3_spi.c @@ -35,6 +35,12 @@ DECLARE_GLOBAL_DATA_PTR; #define OMAP3_MCSPI4_BASE 0x480BA000 #endif +#define OMAP4_MCSPI_REG_OFFSET 0x100 + +struct omap2_mcspi_platform_config { + unsigned int regs_offset; +}; + /* per-register bitmasks */ #define OMAP3_MCSPI_SYSCONFIG_SMARTIDLE (2 << 3) #define OMAP3_MCSPI_SYSCONFIG_ENAWAKEUP BIT(2) @@ -623,7 +629,10 @@ static int omap3_spi_probe(struct udevice *dev) const void *blob = gd->fdt_blob; int node = dev->of_offset; - priv->regs = (struct mcspi *)dev_get_addr(dev); + struct omap2_mcspi_platform_config* data = + (struct omap2_mcspi_platform_config*)dev_get_driver_data(dev); + + priv->regs = (struct mcspi *)(dev_get_addr(dev) + data->regs_offset); priv->pin_dir = fdtdec_get_uint(blob, node, "ti,pindir-d0-out-d1-in", MCSPI_PINDIR_D0_IN_D1_OUT); priv->wordlen = SPI_DEFAULT_WORDLEN; @@ -662,9 +671,17 @@ static const struct dm_spi_ops omap3_spi_ops = { */ }; +static struct omap2_mcspi_platform_config omap2_pdata = { + .regs_offset = 0, +}; + +static struct omap2_mcspi_platform_config omap4_pdata = { + .regs_offset = OMAP4_MCSPI_REG_OFFSET, +}; + static const struct udevice_id omap3_spi_ids[] = { - { .compatible = "ti,omap2-mcspi" }, - { .compatible = "ti,omap4-mcspi" }, + { .compatible = "ti,omap2-mcspi", .data = (ulong)&omap2_pdata }, + { .compatible = "ti,omap4-mcspi", .data = (ulong)&omap4_pdata }, { } }; From d550e82e4efebf5995809e38e8fb029b8fe6e861 Mon Sep 17 00:00:00 2001 From: Tom Rini Date: Mon, 23 May 2016 11:51:13 -0400 Subject: [PATCH 161/162] SPL: fat: Fix spl_parse_image_header() return value handling The spl_parse_image_header() can return 0 and it is not an error. Only treat non-zero return value as an error. Signed-off-by: Marek Vasut Reviewed-by: Fabio Estevam Reviewed-by: Peng Fan Reviewed-by: Stefano Babic Reviewed-by: Tom Rini --- common/spl/spl_fat.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/spl/spl_fat.c b/common/spl/spl_fat.c index 338ea2f092..5b0d96925e 100644 --- a/common/spl/spl_fat.c +++ b/common/spl/spl_fat.c @@ -58,7 +58,7 @@ int spl_load_image_fat(struct blk_desc *block_dev, goto end; err = spl_parse_image_header(header); - if (err <= 0) + if (err) goto end; err = file_fat_read(filename, (u8 *)spl_image.load_addr, 0); From d38fca40c84e6d5f73dfe43cef4c46d42f90aa66 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Fri, 20 May 2016 12:13:10 +0900 Subject: [PATCH 162/162] ARM: fix ifdef in ARMv8 lowlevel_init() again Commit 116611937faa ("ARM: fix ifdefs in ARMv8 lowlevel_init()") accidentally inverted the logic of CONFIG_ARMV8_MULTIENTRY. Fixes: 116611937faa ("ARM: fix ifdefs in ARMv8 lowlevel_init()") Signed-off-by: Masahiro Yamada Reviewed-by: Stephen Warren --- arch/arm/cpu/armv8/start.S | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/cpu/armv8/start.S b/arch/arm/cpu/armv8/start.S index c3cc8199ca..e933021a17 100644 --- a/arch/arm/cpu/armv8/start.S +++ b/arch/arm/cpu/armv8/start.S @@ -216,7 +216,7 @@ WEAK(lowlevel_init) #endif #endif -#ifndef CONFIG_ARMV8_MULTIENTRY +#ifdef CONFIG_ARMV8_MULTIENTRY branch_if_master x0, x1, 2f /*