diff options
Diffstat (limited to 'drivers')
39 files changed, 1286 insertions, 353 deletions
diff --git a/drivers/block/ahci.c b/drivers/block/ahci.c index c8f6573..4df8046 100644 --- a/drivers/block/ahci.c +++ b/drivers/block/ahci.c @@ -41,7 +41,7 @@ u16 *ataid[AHCI_MAX_PORTS]; #define WAIT_MS_SPINUP 20000 #define WAIT_MS_DATAIO 5000 #define WAIT_MS_FLUSH 5000 -#define WAIT_MS_LINKUP 40 +#define WAIT_MS_LINKUP 200 static inline u32 ahci_port_base(u32 base, u32 port) { diff --git a/drivers/core/device.c b/drivers/core/device.c index c73c339..166b073 100644 --- a/drivers/core/device.c +++ b/drivers/core/device.c @@ -10,6 +10,7 @@ */ #include <common.h> +#include <fdtdec.h> #include <malloc.h> #include <dm/device.h> #include <dm/device-internal.h> @@ -21,6 +22,8 @@ #include <linux/err.h> #include <linux/list.h> +DECLARE_GLOBAL_DATA_PTR; + /** * device_chld_unbind() - Unbind all device's children from the device * @@ -95,6 +98,21 @@ int device_bind(struct udevice *parent, struct driver *drv, const char *name, dev->parent = parent; dev->driver = drv; dev->uclass = uc; + + /* + * For some devices, such as a SPI or I2C bus, the 'reg' property + * is a reasonable indicator of the sequence number. But if there is + * an alias, we use that in preference. In any case, this is just + * a 'requested' sequence, and will be resolved (and ->seq updated) + * when the device is probed. + */ + dev->req_seq = fdtdec_get_int(gd->fdt_blob, of_offset, "reg", -1); + dev->seq = -1; + if (uc->uc_drv->name && of_offset != -1) { + fdtdec_get_alias_seq(gd->fdt_blob, uc->uc_drv->name, of_offset, + &dev->req_seq); + } + if (!dev->platdata && drv->platdata_auto_alloc_size) dev->flags |= DM_FLAG_ALLOC_PDATA; @@ -129,14 +147,16 @@ fail_bind: return ret; } -int device_bind_by_name(struct udevice *parent, const struct driver_info *info, - struct udevice **devp) +int device_bind_by_name(struct udevice *parent, bool pre_reloc_only, + const struct driver_info *info, struct udevice **devp) { struct driver *drv; drv = lists_driver_lookup_name(info->name); if (!drv) return -ENOENT; + if (pre_reloc_only && !(drv->flags & DM_FLAG_PRE_RELOC)) + return -EPERM; return device_bind(parent, drv, info->name, (void *)info->platdata, -1, devp); @@ -198,6 +218,13 @@ static void device_free(struct udevice *dev) free(dev->uclass_priv); dev->uclass_priv = NULL; } + if (dev->parent) { + size = dev->parent->driver->per_child_auto_alloc_size; + if (size) { + free(dev->parent_priv); + dev->parent_priv = NULL; + } + } } int device_probe(struct udevice *dev) @@ -205,6 +232,7 @@ int device_probe(struct udevice *dev) struct driver *drv; int size = 0; int ret; + int seq; if (!dev) return -EINVAL; @@ -242,11 +270,33 @@ int device_probe(struct udevice *dev) /* Ensure all parents are probed */ if (dev->parent) { + size = dev->parent->driver->per_child_auto_alloc_size; + if (size) { + dev->parent_priv = calloc(1, size); + if (!dev->parent_priv) { + ret = -ENOMEM; + goto fail; + } + } + ret = device_probe(dev->parent); if (ret) goto fail; } + seq = uclass_resolve_seq(dev); + if (seq < 0) { + ret = seq; + goto fail; + } + dev->seq = seq; + + if (dev->parent && dev->parent->driver->child_pre_probe) { + ret = dev->parent->driver->child_pre_probe(dev); + if (ret) + goto fail; + } + if (drv->ofdata_to_platdata && dev->of_offset >= 0) { ret = drv->ofdata_to_platdata(dev); if (ret) @@ -274,6 +324,7 @@ fail_uclass: __func__, dev->name); } fail: + dev->seq = -1; device_free(dev); return ret; @@ -307,11 +358,20 @@ int device_remove(struct udevice *dev) goto err_remove; } + if (dev->parent && dev->parent->driver->child_post_remove) { + ret = dev->parent->driver->child_post_remove(dev); + if (ret) { + dm_warn("%s: Device '%s' failed child_post_remove()", + __func__, dev->name); + } + } + device_free(dev); + dev->seq = -1; dev->flags &= ~DM_FLAG_ACTIVATED; - return 0; + return ret; err_remove: /* We can't put the children back */ @@ -346,3 +406,106 @@ void *dev_get_priv(struct udevice *dev) return dev->priv; } + +void *dev_get_parentdata(struct udevice *dev) +{ + if (!dev) { + dm_warn("%s: null device", __func__); + return NULL; + } + + return dev->parent_priv; +} + +static int device_get_device_tail(struct udevice *dev, int ret, + struct udevice **devp) +{ + if (ret) + return ret; + + ret = device_probe(dev); + if (ret) + return ret; + + *devp = dev; + + return 0; +} + +int device_get_child(struct udevice *parent, int index, struct udevice **devp) +{ + struct udevice *dev; + + list_for_each_entry(dev, &parent->child_head, sibling_node) { + if (!index--) + return device_get_device_tail(dev, 0, devp); + } + + return -ENODEV; +} + +int device_find_child_by_seq(struct udevice *parent, int seq_or_req_seq, + bool find_req_seq, struct udevice **devp) +{ + struct udevice *dev; + + *devp = NULL; + if (seq_or_req_seq == -1) + return -ENODEV; + + list_for_each_entry(dev, &parent->child_head, sibling_node) { + if ((find_req_seq ? dev->req_seq : dev->seq) == + seq_or_req_seq) { + *devp = dev; + return 0; + } + } + + return -ENODEV; +} + +int device_get_child_by_seq(struct udevice *parent, int seq, + struct udevice **devp) +{ + struct udevice *dev; + int ret; + + *devp = NULL; + ret = device_find_child_by_seq(parent, seq, false, &dev); + if (ret == -ENODEV) { + /* + * We didn't find it in probed devices. See if there is one + * that will request this seq if probed. + */ + ret = device_find_child_by_seq(parent, seq, true, &dev); + } + return device_get_device_tail(dev, ret, devp); +} + +int device_find_child_by_of_offset(struct udevice *parent, int of_offset, + struct udevice **devp) +{ + struct udevice *dev; + + *devp = NULL; + + list_for_each_entry(dev, &parent->child_head, sibling_node) { + if (dev->of_offset == of_offset) { + *devp = dev; + return 0; + } + } + + return -ENODEV; +} + +int device_get_child_by_of_offset(struct udevice *parent, int seq, + struct udevice **devp) +{ + struct udevice *dev; + int ret; + + *devp = NULL; + ret = device_find_child_by_of_offset(parent, seq, &dev); + return device_get_device_tail(dev, ret, devp); +} diff --git a/drivers/core/lists.c b/drivers/core/lists.c index afb59d1..0f08bfd 100644 --- a/drivers/core/lists.c +++ b/drivers/core/lists.c @@ -11,6 +11,7 @@ #include <errno.h> #include <dm/device.h> #include <dm/device-internal.h> +#include <dm/lists.h> #include <dm/platdata.h> #include <dm/uclass.h> #include <dm/util.h> @@ -61,7 +62,7 @@ struct uclass_driver *lists_uclass_lookup(enum uclass_id id) return NULL; } -int lists_bind_drivers(struct udevice *parent) +int lists_bind_drivers(struct udevice *parent, bool pre_reloc_only) { struct driver_info *info = ll_entry_start(struct driver_info, driver_info); @@ -72,8 +73,8 @@ int lists_bind_drivers(struct udevice *parent) int ret; for (entry = info; entry != info + n_ents; entry++) { - ret = device_bind_by_name(parent, entry, &dev); - if (ret) { + ret = device_bind_by_name(parent, pre_reloc_only, entry, &dev); + if (ret && ret != -EPERM) { dm_warn("No match for driver '%s'\n", entry->name); if (!result || ret != -ENOENT) result = ret; @@ -123,16 +124,19 @@ int lists_bind_fdt(struct udevice *parent, const void *blob, int offset) const int n_ents = ll_entry_count(struct driver, driver); struct driver *entry; struct udevice *dev; + bool found = false; const char *name; int result = 0; - int ret; + int ret = 0; dm_dbg("bind node %s\n", fdt_get_name(blob, offset, NULL)); for (entry = driver; entry != driver + n_ents; entry++) { ret = driver_check_compatible(blob, offset, entry->of_match); + name = fdt_get_name(blob, offset, NULL); if (ret == -ENOENT) { continue; } else if (ret == -ENODEV) { + dm_dbg("Device '%s' has no compatible string\n", name); break; } else if (ret) { dm_warn("Device tree error at offset %d\n", offset); @@ -141,14 +145,21 @@ int lists_bind_fdt(struct udevice *parent, const void *blob, int offset) break; } - name = fdt_get_name(blob, offset, NULL); dm_dbg(" - found match at '%s'\n", entry->name); ret = device_bind(parent, entry, name, NULL, offset, &dev); if (ret) { - dm_warn("No match for driver '%s'\n", entry->name); + dm_warn("Error binding driver '%s'\n", entry->name); if (!result || ret != -ENOENT) result = ret; + } else { + found = true; } + break; + } + + if (!found && !result && ret != -ENODEV) { + dm_dbg("No match for node '%s'\n", + fdt_get_name(blob, offset, NULL)); } return result; diff --git a/drivers/core/root.c b/drivers/core/root.c index 1cbb096..393dd98 100644 --- a/drivers/core/root.c +++ b/drivers/core/root.c @@ -15,6 +15,7 @@ #include <dm/device-internal.h> #include <dm/lists.h> #include <dm/platdata.h> +#include <dm/root.h> #include <dm/uclass.h> #include <dm/util.h> #include <linux/list.h> @@ -45,18 +46,29 @@ int dm_init(void) } INIT_LIST_HEAD(&DM_UCLASS_ROOT_NON_CONST); - ret = device_bind_by_name(NULL, &root_info, &DM_ROOT_NON_CONST); + ret = device_bind_by_name(NULL, false, &root_info, &DM_ROOT_NON_CONST); if (ret) return ret; + ret = device_probe(DM_ROOT_NON_CONST); + if (ret) + return ret; + + return 0; +} + +int dm_uninit(void) +{ + device_remove(dm_root()); + device_unbind(dm_root()); return 0; } -int dm_scan_platdata(void) +int dm_scan_platdata(bool pre_reloc_only) { int ret; - ret = lists_bind_drivers(DM_ROOT_NON_CONST); + ret = lists_bind_drivers(DM_ROOT_NON_CONST, pre_reloc_only); if (ret == -ENOENT) { dm_warn("Some drivers were not found\n"); ret = 0; @@ -68,27 +80,66 @@ int dm_scan_platdata(void) } #ifdef CONFIG_OF_CONTROL -int dm_scan_fdt(const void *blob) +int dm_scan_fdt_node(struct udevice *parent, const void *blob, int offset, + bool pre_reloc_only) { - int offset = 0; int ret = 0, err; - int depth = 0; - do { - offset = fdt_next_node(blob, offset, &depth); - if (offset > 0 && depth == 1) { - err = lists_bind_fdt(gd->dm_root, blob, offset); - if (err && !ret) - ret = err; - } - } while (offset > 0); + for (offset = fdt_first_subnode(blob, offset); + offset > 0; + offset = fdt_next_subnode(blob, offset)) { + if (pre_reloc_only && + !fdt_getprop(blob, offset, "u-boot,dm-pre-reloc", NULL)) + continue; + err = lists_bind_fdt(parent, blob, offset); + if (err && !ret) + ret = err; + } if (ret) dm_warn("Some drivers failed to bind\n"); return ret; } + +int dm_scan_fdt(const void *blob, bool pre_reloc_only) +{ + return dm_scan_fdt_node(gd->dm_root, blob, 0, pre_reloc_only); +} +#endif + +__weak int dm_scan_other(bool pre_reloc_only) +{ + return 0; +} + +int dm_init_and_scan(bool pre_reloc_only) +{ + int ret; + + ret = dm_init(); + if (ret) { + debug("dm_init() failed: %d\n", ret); + return ret; + } + ret = dm_scan_platdata(pre_reloc_only); + if (ret) { + debug("dm_scan_platdata() failed: %d\n", ret); + return ret; + } +#ifdef CONFIG_OF_CONTROL + ret = dm_scan_fdt(gd->fdt_blob, pre_reloc_only); + if (ret) { + debug("dm_scan_fdt() failed: %d\n", ret); + return ret; + } #endif + ret = dm_scan_other(pre_reloc_only); + if (ret) + return ret; + + return 0; +} /* This is the root driver - all drivers are children of this */ U_BOOT_DRIVER(root_driver) = { diff --git a/drivers/core/uclass.c b/drivers/core/uclass.c index 34723ec..61ca17e 100644 --- a/drivers/core/uclass.c +++ b/drivers/core/uclass.c @@ -23,6 +23,8 @@ struct uclass *uclass_find(enum uclass_id key) { struct uclass *uc; + if (!gd->dm_root) + return NULL; /* * TODO(sjg@chromium.org): Optimise this, perhaps moving the found * node to the start of the list, or creating a linear array mapping @@ -158,13 +160,72 @@ int uclass_find_device(enum uclass_id id, int index, struct udevice **devp) return -ENODEV; } -int uclass_get_device(enum uclass_id id, int index, struct udevice **devp) +int uclass_find_device_by_seq(enum uclass_id id, int seq_or_req_seq, + bool find_req_seq, struct udevice **devp) { + struct uclass *uc; struct udevice *dev; int ret; *devp = NULL; - ret = uclass_find_device(id, index, &dev); + debug("%s: %d %d\n", __func__, find_req_seq, seq_or_req_seq); + if (seq_or_req_seq == -1) + return -ENODEV; + ret = uclass_get(id, &uc); + if (ret) + return ret; + + list_for_each_entry(dev, &uc->dev_head, uclass_node) { + debug(" - %d %d\n", dev->req_seq, dev->seq); + if ((find_req_seq ? dev->req_seq : dev->seq) == + seq_or_req_seq) { + *devp = dev; + debug(" - found\n"); + return 0; + } + } + debug(" - not found\n"); + + return -ENODEV; +} + +static int uclass_find_device_by_of_offset(enum uclass_id id, int node, + struct udevice **devp) +{ + struct uclass *uc; + struct udevice *dev; + int ret; + + *devp = NULL; + if (node < 0) + return -ENODEV; + ret = uclass_get(id, &uc); + if (ret) + return ret; + + list_for_each_entry(dev, &uc->dev_head, uclass_node) { + if (dev->of_offset == node) { + *devp = dev; + return 0; + } + } + + return -ENODEV; +} + +/** + * uclass_get_device_tail() - handle the end of a get_device call + * + * This handles returning an error or probing a device as needed. + * + * @dev: Device that needs to be probed + * @ret: Error to return. If non-zero then the device is not probed + * @devp: Returns the value of 'dev' if there is no error + * @return ret, if non-zero, else the result of the device_probe() call + */ +static int uclass_get_device_tail(struct udevice *dev, int ret, + struct udevice **devp) +{ if (ret) return ret; @@ -177,6 +238,44 @@ int uclass_get_device(enum uclass_id id, int index, struct udevice **devp) return 0; } +int uclass_get_device(enum uclass_id id, int index, struct udevice **devp) +{ + struct udevice *dev; + int ret; + + *devp = NULL; + ret = uclass_find_device(id, index, &dev); + return uclass_get_device_tail(dev, ret, devp); +} + +int uclass_get_device_by_seq(enum uclass_id id, int seq, struct udevice **devp) +{ + struct udevice *dev; + int ret; + + *devp = NULL; + ret = uclass_find_device_by_seq(id, seq, false, &dev); + if (ret == -ENODEV) { + /* + * We didn't find it in probed devices. See if there is one + * that will request this seq if probed. + */ + ret = uclass_find_device_by_seq(id, seq, true, &dev); + } + return uclass_get_device_tail(dev, ret, devp); +} + +int uclass_get_device_by_of_offset(enum uclass_id id, int node, + struct udevice **devp) +{ + struct udevice *dev; + int ret; + + *devp = NULL; + ret = uclass_find_device_by_of_offset(id, node, &dev); + return uclass_get_device_tail(dev, ret, devp); +} + int uclass_first_device(enum uclass_id id, struct udevice **devp) { struct uclass *uc; @@ -254,6 +353,37 @@ int uclass_unbind_device(struct udevice *dev) return 0; } +int uclass_resolve_seq(struct udevice *dev) +{ + struct udevice *dup; + int seq; + int ret; + + assert(dev->seq == -1); + ret = uclass_find_device_by_seq(dev->uclass->uc_drv->id, dev->req_seq, + false, &dup); + if (!ret) { + dm_warn("Device '%s': seq %d is in use by '%s'\n", + dev->name, dev->req_seq, dup->name); + } else if (ret == -ENODEV) { + /* Our requested sequence number is available */ + if (dev->req_seq != -1) + return dev->req_seq; + } else { + return ret; + } + + for (seq = 0; seq < DM_MAX_SEQ; seq++) { + ret = uclass_find_device_by_seq(dev->uclass->uc_drv->id, seq, + false, &dup); + if (ret == -ENODEV) + break; + if (ret) + return ret; + } + return seq; +} + int uclass_post_probe_device(struct udevice *dev) { struct uclass_driver *uc_drv = dev->uclass->uc_drv; @@ -281,6 +411,7 @@ int uclass_pre_remove_device(struct udevice *dev) free(dev->uclass_priv); dev->uclass_priv = NULL; } + dev->seq = -1; return 0; } diff --git a/drivers/demo/demo-uclass.c b/drivers/demo/demo-uclass.c index 636fd88..f6510d6 100644 --- a/drivers/demo/demo-uclass.c +++ b/drivers/demo/demo-uclass.c @@ -19,6 +19,7 @@ DECLARE_GLOBAL_DATA_PTR; UCLASS_DRIVER(demo) = { + .name = "demo", .id = UCLASS_DEMO, }; diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index 4e001e1..aa11f15 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -5,7 +5,9 @@ # SPDX-License-Identifier: GPL-2.0+ # +ifndef CONFIG_SPL_BUILD obj-$(CONFIG_DM_GPIO) += gpio-uclass.o +endif obj-$(CONFIG_AT91_GPIO) += at91_gpio.o obj-$(CONFIG_INTEL_ICH6_GPIO) += intel_ich6_gpio.o @@ -34,3 +36,4 @@ obj-$(CONFIG_XILINX_GPIO) += xilinx_gpio.o obj-$(CONFIG_ADI_GPIO2) += adi_gpio2.o obj-$(CONFIG_TCA642X) += tca642x.o oby-$(CONFIG_SX151X) += sx151x.o +obj-$(CONFIG_SUNXI_GPIO) += sunxi_gpio.o diff --git a/drivers/gpio/sunxi_gpio.c b/drivers/gpio/sunxi_gpio.c new file mode 100644 index 0000000..0c50a8f --- /dev/null +++ b/drivers/gpio/sunxi_gpio.c @@ -0,0 +1,102 @@ +/* + * (C) Copyright 2012 Henrik Nordstrom <henrik@henriknordstrom.net> + * + * Based on earlier arch/arm/cpu/armv7/sunxi/gpio.c: + * + * (C) Copyright 2007-2011 + * Allwinner Technology Co., Ltd. <www.allwinnertech.com> + * Tom Cubie <tangliang@allwinnertech.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/gpio.h> + +static int sunxi_gpio_output(u32 pin, u32 val) +{ + u32 dat; + u32 bank = GPIO_BANK(pin); + u32 num = GPIO_NUM(pin); + struct sunxi_gpio *pio = BANK_TO_GPIO(bank); + + dat = readl(&pio->dat); + if (val) + dat |= 0x1 << num; + else + dat &= ~(0x1 << num); + + writel(dat, &pio->dat); + + return 0; +} + +static int sunxi_gpio_input(u32 pin) +{ + u32 dat; + u32 bank = GPIO_BANK(pin); + u32 num = GPIO_NUM(pin); + struct sunxi_gpio *pio = BANK_TO_GPIO(bank); + + dat = readl(&pio->dat); + dat >>= num; + + return dat & 0x1; +} + +int gpio_request(unsigned gpio, const char *label) +{ + return 0; +} + +int gpio_free(unsigned gpio) +{ + return 0; +} + +int gpio_direction_input(unsigned gpio) +{ + sunxi_gpio_set_cfgpin(gpio, SUNXI_GPIO_INPUT); + + return sunxi_gpio_input(gpio); +} + +int gpio_direction_output(unsigned gpio, int value) +{ + sunxi_gpio_set_cfgpin(gpio, SUNXI_GPIO_OUTPUT); + + return sunxi_gpio_output(gpio, value); +} + +int gpio_get_value(unsigned gpio) +{ + return sunxi_gpio_input(gpio); +} + +int gpio_set_value(unsigned gpio, int value) +{ + return sunxi_gpio_output(gpio, value); +} + +int sunxi_name_to_gpio(const char *name) +{ + int group = 0; + int groupsize = 9 * 32; + long pin; + char *eptr; + if (*name == 'P' || *name == 'p') + name++; + if (*name >= 'A') { + group = *name - (*name > 'a' ? 'a' : 'A'); + groupsize = 32; + name++; + } + + pin = simple_strtol(name, &eptr, 10); + if (!*name || *eptr) + return -1; + if (pin < 0 || pin > groupsize || group >= 9) + return -1; + return group * 32 + pin; +} diff --git a/drivers/i2c/Makefile b/drivers/i2c/Makefile index 96bd45d..416ea4f 100644 --- a/drivers/i2c/Makefile +++ b/drivers/i2c/Makefile @@ -7,7 +7,6 @@ obj-$(CONFIG_BFIN_TWI_I2C) += bfin-twi_i2c.o obj-$(CONFIG_DW_I2C) += designware_i2c.o -obj-$(CONFIG_I2C_MVTWSI) += mvtwsi.o obj-$(CONFIG_I2C_MV) += mv_i2c.o obj-$(CONFIG_I2C_MXS) += mxs_i2c.o obj-$(CONFIG_PCA9564_I2C) += pca9564_i2c.o @@ -20,6 +19,7 @@ obj-$(CONFIG_SYS_I2C_FSL) += fsl_i2c.o obj-$(CONFIG_SYS_I2C_FTI2C010) += fti2c010.o obj-$(CONFIG_SYS_I2C_IHS) += ihs_i2c.o obj-$(CONFIG_SYS_I2C_KONA) += kona_i2c.o +obj-$(CONFIG_SYS_I2C_MVTWSI) += mvtwsi.o obj-$(CONFIG_SYS_I2C_MXC) += mxc_i2c.o obj-$(CONFIG_SYS_I2C_OMAP24XX) += omap24xx_i2c.o obj-$(CONFIG_SYS_I2C_OMAP34XX) += omap24xx_i2c.o diff --git a/drivers/i2c/fsl_i2c.c b/drivers/i2c/fsl_i2c.c index aa159f8..811033b 100644 --- a/drivers/i2c/fsl_i2c.c +++ b/drivers/i2c/fsl_i2c.c @@ -46,10 +46,16 @@ DECLARE_GLOBAL_DATA_PTR; -static const struct fsl_i2c *i2c_dev[2] = { +static const struct fsl_i2c *i2c_dev[4] = { (struct fsl_i2c *)(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 *)(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), +#endif +#ifdef CONFIG_SYS_FSL_I2C4_OFFSET + (struct fsl_i2c *)(CONFIG_SYS_IMMR + CONFIG_SYS_FSL_I2C4_OFFSET) #endif }; @@ -539,3 +545,15 @@ U_BOOT_I2C_ADAP_COMPLETE(fsl_1, fsl_i2c_init, fsl_i2c_probe, fsl_i2c_read, 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, + 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, + fsl_i2c_write, fsl_i2c_set_bus_speed, + CONFIG_SYS_FSL_I2C4_SPEED, CONFIG_SYS_FSL_I2C4_SLAVE, + 3) +#endif diff --git a/drivers/i2c/mvtwsi.c b/drivers/i2c/mvtwsi.c index 5ba0e03..ab3ffa0 100644 --- a/drivers/i2c/mvtwsi.c +++ b/drivers/i2c/mvtwsi.c @@ -22,6 +22,8 @@ #include <asm/arch/orion5x.h> #elif defined(CONFIG_KIRKWOOD) #include <asm/arch/kirkwood.h> +#elif defined(CONFIG_SUNXI) +#include <asm/arch/i2c.h> #else #error Driver mvtwsi not supported by SoC or board #endif @@ -30,6 +32,20 @@ * TWSI register structure */ +#ifdef CONFIG_SUNXI + +struct mvtwsi_registers { + u32 slave_address; + u32 xtnd_slave_addr; + u32 data; + u32 control; + u32 status; + u32 baudrate; + u32 soft_reset; +}; + +#else + struct mvtwsi_registers { u32 slave_address; u32 data; @@ -43,6 +59,8 @@ struct mvtwsi_registers { u32 soft_reset; }; +#endif + /* * Control register fields */ @@ -220,11 +238,10 @@ static int twsi_stop(int status) /* * Reset controller. - * Called at end of i2c_init unsuccessful i2c transactions. * Controller reset also resets the baud rate and slave address, so - * re-establish them. + * they must be re-established afterwards. */ -static void twsi_reset(u8 baud_rate, u8 slave_address) +static void twsi_reset(struct i2c_adapter *adap) { /* ensure controller will be enabled by any twsi*() function */ twsi_control_flags = MVTWSI_CONTROL_TWSIEN; @@ -232,23 +249,17 @@ static void twsi_reset(u8 baud_rate, u8 slave_address) writel(0, &twsi->soft_reset); /* wait 2 ms -- this is what the Marvell LSP does */ udelay(20000); - /* set baud rate */ - writel(baud_rate, &twsi->baudrate); - /* set slave address even though we don't use it */ - writel(slave_address, &twsi->slave_address); - writel(0, &twsi->xtnd_slave_addr); - /* assert STOP but don't care for the result */ - (void) twsi_stop(0); } /* * I2C init called by cmd_i2c when doing 'i2c reset'. * Sets baud to the highest possible value not exceeding requested one. */ -void i2c_init(int requested_speed, int slaveadd) +static unsigned int twsi_i2c_set_bus_speed(struct i2c_adapter *adap, + unsigned int requested_speed) { - int tmp_speed, highest_speed, n, m; - int baud = 0x44; /* baudrate at controller reset */ + unsigned int tmp_speed, highest_speed, n, m; + unsigned int baud = 0x44; /* baudrate at controller reset */ /* use actual speed to collect progressively higher values */ highest_speed = 0; @@ -263,8 +274,21 @@ void i2c_init(int requested_speed, int slaveadd) } } } + writel(baud, &twsi->baudrate); + return 0; +} + +static void twsi_i2c_init(struct i2c_adapter *adap, int speed, int slaveadd) +{ /* reset controller */ - twsi_reset(baud, slaveadd); + twsi_reset(adap); + /* set speed */ + twsi_i2c_set_bus_speed(adap, speed); + /* set slave address even though we don't use it */ + writel(slaveadd, &twsi->slave_address); + writel(0, &twsi->xtnd_slave_addr); + /* assert STOP but don't care for the result */ + (void) twsi_stop(0); } /* @@ -294,7 +318,7 @@ static int i2c_begin(int expected_start_status, u8 addr) * I2C probe called by cmd_i2c when doing 'i2c probe'. * Begin read, nak data byte, end. */ -int i2c_probe(uchar chip) +static int twsi_i2c_probe(struct i2c_adapter *adap, uchar chip) { u8 dummy_byte; int status; @@ -320,12 +344,13 @@ int i2c_probe(uchar chip) * cmd_eeprom, so we have to choose here, and for the moment that'll be * a repeated start without a preceding stop. */ -int i2c_read(u8 dev, uint addr, int alen, u8 *data, int length) +static int twsi_i2c_read(struct i2c_adapter *adap, uchar chip, uint addr, + int alen, uchar *data, int length) { int status; /* begin i2c write to send the address bytes */ - status = i2c_begin(MVTWSI_STATUS_START, (dev << 1)); + status = i2c_begin(MVTWSI_STATUS_START, (chip << 1)); /* send addr bytes */ while ((status == 0) && alen--) status = twsi_send(addr >> (8*alen), @@ -333,7 +358,7 @@ int i2c_read(u8 dev, uint addr, int alen, u8 *data, int length) /* begin i2c read to receive eeprom data bytes */ if (status == 0) status = i2c_begin( - MVTWSI_STATUS_REPEATED_START, (dev << 1) | 1); + MVTWSI_STATUS_REPEATED_START, (chip << 1) | 1); /* prepare ACK if at least one byte must be received */ if (length > 0) twsi_control_flags |= MVTWSI_CONTROL_ACK; @@ -355,12 +380,13 @@ int i2c_read(u8 dev, uint addr, int alen, u8 *data, int length) * I2C write called by cmd_i2c when doing 'i2c write' and by cmd_eeprom.c * Begin write, send address byte(s), send data bytes, end. */ -int i2c_write(u8 dev, uint addr, int alen, u8 *data, int length) +static int twsi_i2c_write(struct i2c_adapter *adap, uchar chip, uint addr, + int alen, uchar *data, int length) { int status; /* begin i2c write to send the eeprom adress bytes then data bytes */ - status = i2c_begin(MVTWSI_STATUS_START, (dev << 1)); + status = i2c_begin(MVTWSI_STATUS_START, (chip << 1)); /* send addr bytes */ while ((status == 0) && alen--) status = twsi_send(addr >> (8*alen), @@ -374,21 +400,7 @@ int i2c_write(u8 dev, uint addr, int alen, u8 *data, int length) return status; } -/* - * Bus set routine: we only support bus 0. - */ -int i2c_set_bus_num(unsigned int bus) -{ - if (bus > 0) { - return -1; - } - return 0; -} - -/* - * Bus get routine: hard-return bus 0. - */ -unsigned int i2c_get_bus_num(void) -{ - return 0; -} +U_BOOT_I2C_ADAP_COMPLETE(twsi0, twsi_i2c_init, twsi_i2c_probe, + twsi_i2c_read, twsi_i2c_write, + twsi_i2c_set_bus_speed, + CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE, 0) diff --git a/drivers/i2c/omap24xx_i2c.c b/drivers/i2c/omap24xx_i2c.c index a39b591..0f1e35c 100644 --- a/drivers/i2c/omap24xx_i2c.c +++ b/drivers/i2c/omap24xx_i2c.c @@ -153,11 +153,60 @@ static uint omap24_i2c_setspeed(struct i2c_adapter *adap, uint speed) return 0; } + +static void omap24_i2c_deblock(struct i2c_adapter *adap) +{ + struct i2c *i2c_base = omap24_get_base(adap); + int i; + u16 systest; + u16 orgsystest; + + /* set test mode ST_EN = 1 */ + orgsystest = readw(&i2c_base->systest); + systest = orgsystest; + /* enable testmode */ + systest |= I2C_SYSTEST_ST_EN; + writew(systest, &i2c_base->systest); + systest &= ~I2C_SYSTEST_TMODE_MASK; + systest |= 3 << I2C_SYSTEST_TMODE_SHIFT; + writew(systest, &i2c_base->systest); + + /* set SCL, SDA = 1 */ + systest |= I2C_SYSTEST_SCL_O | I2C_SYSTEST_SDA_O; + writew(systest, &i2c_base->systest); + udelay(10); + + /* toggle scl 9 clocks */ + for (i = 0; i < 9; i++) { + /* SCL = 0 */ + systest &= ~I2C_SYSTEST_SCL_O; + writew(systest, &i2c_base->systest); + udelay(10); + /* SCL = 1 */ + systest |= I2C_SYSTEST_SCL_O; + writew(systest, &i2c_base->systest); + udelay(10); + } + + /* send stop */ + systest &= ~I2C_SYSTEST_SDA_O; + writew(systest, &i2c_base->systest); + udelay(10); + systest |= I2C_SYSTEST_SCL_O | I2C_SYSTEST_SDA_O; + writew(systest, &i2c_base->systest); + udelay(10); + + /* restore original mode */ + writew(orgsystest, &i2c_base->systest); +} + static void omap24_i2c_init(struct i2c_adapter *adap, int speed, int slaveadd) { struct i2c *i2c_base = omap24_get_base(adap); int timeout = I2C_TIMEOUT; + int deblock = 1; +retry: if (readw(&i2c_base->con) & I2C_CON_EN) { writew(0, &i2c_base->con); udelay(50000); @@ -194,6 +243,14 @@ static void omap24_i2c_init(struct i2c_adapter *adap, int speed, int slaveadd) udelay(1000); flush_fifo(adap); writew(0xFFFF, &i2c_base->stat); + + /* Handle possible failed I2C state */ + if (wait_for_bb(adap)) + if (deblock == 1) { + omap24_i2c_deblock(adap); + deblock = 0; + goto retry; + } } static void flush_fifo(struct i2c_adapter *adap) diff --git a/drivers/input/cros_ec_keyb.c b/drivers/input/cros_ec_keyb.c index a2501e0..47502b1 100644 --- a/drivers/input/cros_ec_keyb.c +++ b/drivers/input/cros_ec_keyb.c @@ -93,7 +93,7 @@ static int check_for_keys(struct keyb *config, * * @return 0 if no keys available, 1 if keys are available */ -static int kbd_tstc(void) +static int kbd_tstc(struct stdio_dev *dev) { /* Just get input to do this for us */ return config.inited ? input_tstc(&config.input) : 0; @@ -104,7 +104,7 @@ static int kbd_tstc(void) * * @return ASCII key code, or 0 if no key, or -1 if error */ -static int kbd_getc(void) +static int kbd_getc(struct stdio_dev *dev) { /* Just get input to do this for us */ return config.inited ? input_getc(&config.input) : 0; @@ -214,7 +214,7 @@ static int cros_ec_keyb_decode_fdt(const void *blob, int node, * * @return 0 if ok, -1 on error */ -static int cros_ec_init_keyboard(void) +static int cros_ec_init_keyboard(struct stdio_dev *dev) { const void *blob = gd->fdt_blob; int node; diff --git a/drivers/input/i8042.c b/drivers/input/i8042.c index 35fa0bb..ca1604c 100644 --- a/drivers/input/i8042.c +++ b/drivers/input/i8042.c @@ -398,7 +398,7 @@ int i8042_kbd_init(void) * i8042_tstc - test if keyboard input is available * option: cursor blinking if called in a loop */ -int i8042_tstc(void) +int i8042_tstc(struct stdio_dev *dev) { unsigned char scan_code = 0; @@ -432,7 +432,7 @@ int i8042_tstc(void) * i8042_getc - wait till keyboard input is available * option: turn on/off cursor while waiting */ -int i8042_getc(void) +int i8042_getc(struct stdio_dev *dev) { int ret_chr; unsigned char scan_code; diff --git a/drivers/input/keyboard.c b/drivers/input/keyboard.c index 614592e..be0f333 100644 --- a/drivers/input/keyboard.c +++ b/drivers/input/keyboard.c @@ -70,7 +70,7 @@ static void kbd_put_queue(char data) } /* test if a character is in the queue */ -static int kbd_testc(void) +static int kbd_testc(struct stdio_dev *dev) { #if defined(CONFIG_MPC5xxx) || defined(CONFIG_MPC8540) || defined(CONFIG_MPC8541) || defined(CONFIG_MPC8555) /* no ISR is used, so received chars must be polled */ @@ -83,7 +83,7 @@ static int kbd_testc(void) } /* gets the character from the queue */ -static int kbd_getc(void) +static int kbd_getc(struct stdio_dev *dev) { char c; while(in_pointer==out_pointer) { @@ -275,8 +275,6 @@ int kbd_init (void) memset (&kbddev, 0, sizeof(kbddev)); strcpy(kbddev.name, DEVNAME); kbddev.flags = DEV_FLAGS_INPUT | DEV_FLAGS_SYSTEM; - kbddev.putc = NULL ; - kbddev.puts = NULL ; kbddev.getc = kbd_getc ; kbddev.tstc = kbd_testc ; diff --git a/drivers/input/tegra-kbc.c b/drivers/input/tegra-kbc.c index f137f93..7e36db0 100644 --- a/drivers/input/tegra-kbc.c +++ b/drivers/input/tegra-kbc.c @@ -194,7 +194,7 @@ int tegra_kbc_check(struct input_config *input) * * @return 0 if no keys available, 1 if keys are available */ -static int kbd_tstc(void) +static int kbd_tstc(struct stdio_dev *dev) { /* Just get input to do this for us */ return input_tstc(&config.input); @@ -207,7 +207,7 @@ static int kbd_tstc(void) * * @return ASCII key code, or 0 if no key, or -1 if error */ -static int kbd_getc(void) +static int kbd_getc(struct stdio_dev *dev) { /* Just get input to do this for us */ return input_getc(&config.input); @@ -289,7 +289,7 @@ static void tegra_kbc_open(void) * * @return 0 if ok, -ve on error */ -static int init_tegra_keyboard(void) +static int init_tegra_keyboard(struct stdio_dev *dev) { /* check if already created */ if (config.created) diff --git a/drivers/misc/cbmem_console.c b/drivers/misc/cbmem_console.c index 80a84fd..5f85ccf 100644 --- a/drivers/misc/cbmem_console.c +++ b/drivers/misc/cbmem_console.c @@ -31,7 +31,7 @@ struct cbmem_console { static struct cbmem_console *cbmem_console_p; -void cbmemc_putc(char data) +void cbmemc_putc(struct stdio_dev *dev, char data) { int cursor; @@ -40,12 +40,12 @@ void cbmemc_putc(char data) cbmem_console_p->buffer_body[cursor] = data; } -void cbmemc_puts(const char *str) +void cbmemc_puts(struct stdio_dev *dev, const char *str) { char c; while ((c = *str++) != 0) - cbmemc_putc(c); + cbmemc_putc(dev, c); } int cbmemc_init(void) diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c index b5477b1..a26f3ce 100644 --- a/drivers/mmc/mmc.c +++ b/drivers/mmc/mmc.c @@ -21,7 +21,7 @@ static struct list_head mmc_devices; static int cur_dev_num = -1; -int __weak board_mmc_getwp(struct mmc *mmc) +__weak int board_mmc_getwp(struct mmc *mmc) { return -1; } @@ -42,13 +42,11 @@ int mmc_getwp(struct mmc *mmc) return wp; } -int __board_mmc_getcd(struct mmc *mmc) { +__weak int board_mmc_getcd(struct mmc *mmc) +{ return -1; } -int board_mmc_getcd(struct mmc *mmc)__attribute__((weak, - alias("__board_mmc_getcd"))); - int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data) { int ret; @@ -377,7 +375,7 @@ static int mmc_send_op_cond_iter(struct mmc *mmc, struct mmc_cmd *cmd, return 0; } -int mmc_send_op_cond(struct mmc *mmc) +static int mmc_send_op_cond(struct mmc *mmc) { struct mmc_cmd cmd; int err, i; @@ -399,7 +397,7 @@ int mmc_send_op_cond(struct mmc *mmc) return IN_PROGRESS; } -int mmc_complete_op_cond(struct mmc *mmc) +static int mmc_complete_op_cond(struct mmc *mmc) { struct mmc_cmd cmd; int timeout = 1000; @@ -1371,17 +1369,17 @@ int mmc_set_dsr(struct mmc *mmc, u16 val) return 0; } -/* - * CPU and board-specific MMC initializations. Aliased function - * signals caller to move on - */ -static int __def_mmc_init(bd_t *bis) +/* CPU-specific MMC initializations */ +__weak int cpu_mmc_init(bd_t *bis) { return -1; } -int cpu_mmc_init(bd_t *bis) __attribute__((weak, alias("__def_mmc_init"))); -int board_mmc_init(bd_t *bis) __attribute__((weak, alias("__def_mmc_init"))); +/* board-specific MMC initializations. */ +__weak int board_mmc_init(bd_t *bis) +{ + return -1; +} #if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT) diff --git a/drivers/mmc/omap_hsmmc.c b/drivers/mmc/omap_hsmmc.c index 17cbb09..5b0c302 100644 --- a/drivers/mmc/omap_hsmmc.c +++ b/drivers/mmc/omap_hsmmc.c @@ -120,7 +120,7 @@ static void omap5_pbias_config(struct mmc *mmc) } #endif -unsigned char mmc_board_init(struct mmc *mmc) +static unsigned char mmc_board_init(struct mmc *mmc) { #if defined(CONFIG_OMAP34XX) t2_t *t2_base = (t2_t *)T2_BASE; diff --git a/drivers/mmc/sunxi_mmc.c b/drivers/mmc/sunxi_mmc.c index eb7b115..d4e574f 100644 --- a/drivers/mmc/sunxi_mmc.c +++ b/drivers/mmc/sunxi_mmc.c @@ -16,28 +16,6 @@ #include <asm/arch/cpu.h> #include <asm/arch/mmc.h> -struct sunxi_mmc_des { - u32 reserved1_1:1; - u32 dic:1; /* disable interrupt on completion */ - u32 last_des:1; /* 1-this data buffer is the last buffer */ - u32 first_des:1; /* 1-data buffer is the first buffer, - 0-data buffer contained in the next - descriptor is 1st buffer */ - u32 des_chain:1; /* 1-the 2nd address in the descriptor is the - next descriptor address */ - u32 end_of_ring:1; /* 1-last descriptor flag when using dual - data buffer in descriptor */ - u32 reserved1_2:24; - u32 card_err_sum:1; /* transfer error flag */ - u32 own:1; /* des owner:1-idma owns it, 0-host owns it */ -#define SDXC_DES_NUM_SHIFT 16 -#define SDXC_DES_BUFFER_MAX_LEN (1 << SDXC_DES_NUM_SHIFT) - u32 data_buf1_sz:16; - u32 data_buf2_sz:16; - u32 buf_addr_ptr1; - u32 buf_addr_ptr2; -}; - struct sunxi_mmc_host { unsigned mmc_no; uint32_t *mclkreg; @@ -189,6 +167,7 @@ static int mmc_core_init(struct mmc *mmc) /* Reset controller */ writel(SUNXI_MMC_GCTRL_RESET, &mmchost->reg->gctrl); + udelay(1000); return 0; } @@ -204,6 +183,9 @@ static int mmc_trans_data_by_cpu(struct mmc *mmc, struct mmc_data *data) unsigned timeout_msecs = 2000; unsigned *buff = (unsigned int *)(reading ? data->dest : data->src); + /* Always read / write data through the CPU */ + setbits_le32(&mmchost->reg->gctrl, SUNXI_MMC_GCTRL_ACCESS_BY_AHB); + for (i = 0; i < (byte_cnt >> 2); i++) { while (readl(&mmchost->reg->status) & status_bit) { if (!timeout_msecs--) @@ -220,85 +202,6 @@ static int mmc_trans_data_by_cpu(struct mmc *mmc, struct mmc_data *data) return 0; } -static int mmc_trans_data_by_dma(struct mmc *mmc, struct mmc_data *data) -{ - struct sunxi_mmc_host *mmchost = mmc->priv; - unsigned byte_cnt = data->blocksize * data->blocks; - unsigned char *buff; - unsigned des_idx = 0; - unsigned buff_frag_num = - (byte_cnt + SDXC_DES_BUFFER_MAX_LEN - 1) >> SDXC_DES_NUM_SHIFT; - unsigned remain; - unsigned i, rval; - ALLOC_CACHE_ALIGN_BUFFER(struct sunxi_mmc_des, pdes, buff_frag_num); - - buff = data->flags & MMC_DATA_READ ? - (unsigned char *)data->dest : (unsigned char *)data->src; - remain = byte_cnt & (SDXC_DES_BUFFER_MAX_LEN - 1); - - flush_cache((unsigned long)buff, (unsigned long)byte_cnt); - for (i = 0; i < buff_frag_num; i++, des_idx++) { - memset((void *)&pdes[des_idx], 0, sizeof(struct sunxi_mmc_des)); - pdes[des_idx].des_chain = 1; - pdes[des_idx].own = 1; - pdes[des_idx].dic = 1; - if (buff_frag_num > 1 && i != buff_frag_num - 1) - pdes[des_idx].data_buf1_sz = 0; /* 0 == max_len */ - else - pdes[des_idx].data_buf1_sz = remain; - - pdes[des_idx].buf_addr_ptr1 = - (u32) buff + i * SDXC_DES_BUFFER_MAX_LEN; - if (i == 0) - pdes[des_idx].first_des = 1; - - if (i == buff_frag_num - 1) { - pdes[des_idx].dic = 0; - pdes[des_idx].last_des = 1; - pdes[des_idx].end_of_ring = 1; - pdes[des_idx].buf_addr_ptr2 = 0; - } else { - pdes[des_idx].buf_addr_ptr2 = (u32)&pdes[des_idx + 1]; - } - } - flush_cache((unsigned long)pdes, - sizeof(struct sunxi_mmc_des) * (des_idx + 1)); - - rval = readl(&mmchost->reg->gctrl); - /* Enable DMA */ - writel(rval | SUNXI_MMC_GCTRL_DMA_RESET | SUNXI_MMC_GCTRL_DMA_ENABLE, - &mmchost->reg->gctrl); - /* Reset iDMA */ - writel(SUNXI_MMC_IDMAC_RESET, &mmchost->reg->dmac); - /* Enable iDMA */ - writel(SUNXI_MMC_IDMAC_FIXBURST | SUNXI_MMC_IDMAC_ENABLE, - &mmchost->reg->dmac); - rval = readl(&mmchost->reg->idie) & - ~(SUNXI_MMC_IDIE_TXIRQ|SUNXI_MMC_IDIE_RXIRQ); - if (data->flags & MMC_DATA_WRITE) - rval |= SUNXI_MMC_IDIE_TXIRQ; - else - rval |= SUNXI_MMC_IDIE_RXIRQ; - writel(rval, &mmchost->reg->idie); - writel((u32) pdes, &mmchost->reg->dlba); - writel((0x2 << 28) | (0x7 << 16) | (0x01 << 3), - &mmchost->reg->ftrglevel); - - return 0; -} - -static void mmc_enable_dma_accesses(struct mmc *mmc, int dma) -{ - struct sunxi_mmc_host *mmchost = mmc->priv; - - unsigned int gctrl = readl(&mmchost->reg->gctrl); - if (dma) - gctrl &= ~SUNXI_MMC_GCTRL_ACCESS_BY_AHB; - else - gctrl |= SUNXI_MMC_GCTRL_ACCESS_BY_AHB; - writel(gctrl, &mmchost->reg->gctrl); -} - static int mmc_rint_wait(struct mmc *mmc, unsigned int timeout_msecs, unsigned int done_bit, const char *what) { @@ -327,7 +230,6 @@ static int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, unsigned int timeout_msecs; int error = 0; unsigned int status = 0; - unsigned int usedma = 0; unsigned int bytecnt = 0; if (mmchost->fatal_err) @@ -378,20 +280,8 @@ static int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, bytecnt = data->blocksize * data->blocks; debug("trans data %d bytes\n", bytecnt); -#if defined(CONFIG_MMC_SUNXI_USE_DMA) && !defined(CONFIG_SPL_BUILD) - if (bytecnt > 64) { -#else - if (0) { -#endif - usedma = 1; - mmc_enable_dma_accesses(mmc, 1); - ret = mmc_trans_data_by_dma(mmc, data); - writel(cmdval | cmd->cmdidx, &mmchost->reg->cmd); - } else { - mmc_enable_dma_accesses(mmc, 0); - writel(cmdval | cmd->cmdidx, &mmchost->reg->cmd); - ret = mmc_trans_data_by_cpu(mmc, data); - } + writel(cmdval | cmd->cmdidx, &mmchost->reg->cmd); + ret = mmc_trans_data_by_cpu(mmc, data); if (ret) { error = readl(&mmchost->reg->rint) & \ SUNXI_MMC_RINT_INTERRUPT_ERROR_BIT; @@ -405,7 +295,7 @@ static int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, goto out; if (data) { - timeout_msecs = usedma ? 120 * bytecnt : 120; + timeout_msecs = 120; debug("cacl timeout %x msec\n", timeout_msecs); error = mmc_rint_wait(mmc, timeout_msecs, data->blocks > 1 ? @@ -442,23 +332,6 @@ static int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, debug("mmc resp 0x%08x\n", cmd->response[0]); } out: - if (data && usedma) { - /* IDMASTAREG - * IDST[0] : idma tx int - * IDST[1] : idma rx int - * IDST[2] : idma fatal bus error - * IDST[4] : idma descriptor invalid - * IDST[5] : idma error summary - * IDST[8] : idma normal interrupt sumary - * IDST[9] : idma abnormal interrupt sumary - */ - status = readl(&mmchost->reg->idst); - writel(status, &mmchost->reg->idst); - writel(0, &mmchost->reg->idie); - writel(0, &mmchost->reg->dmac); - writel(readl(&mmchost->reg->gctrl) & ~SUNXI_MMC_GCTRL_DMA_ENABLE, - &mmchost->reg->gctrl); - } if (error < 0) { writel(SUNXI_MMC_GCTRL_RESET, &mmchost->reg->gctrl); mmc_update_clk(mmc); diff --git a/drivers/mtd/cfi_flash.c b/drivers/mtd/cfi_flash.c index a389cd1..c4b5bc1 100644 --- a/drivers/mtd/cfi_flash.c +++ b/drivers/mtd/cfi_flash.c @@ -2360,7 +2360,7 @@ unsigned long flash_init (void) #endif /* CONFIG_SYS_FLASH_QUIET_TEST */ } #ifdef CONFIG_SYS_FLASH_PROTECTION - else if ((s != NULL) && (strcmp(s, "yes") == 0)) { + else if (strcmp(s, "yes") == 0) { /* * Only the U-Boot image and it's environment * is protected, all other sectors are diff --git a/drivers/mtd/nand/davinci_nand.c b/drivers/mtd/nand/davinci_nand.c index 5d42509..a079b1e 100644 --- a/drivers/mtd/nand/davinci_nand.c +++ b/drivers/mtd/nand/davinci_nand.c @@ -305,6 +305,189 @@ static struct nand_ecclayout nand_davinci_4bit_layout_oobfirst = { #endif }; +#if defined CONFIG_KEYSTONE_RBL_NAND +#if defined(CONFIG_SYS_NAND_PAGE_2K) +static struct nand_ecclayout nand_keystone_rbl_4bit_layout_oobfirst = { + .eccbytes = 40, + .eccpos = { + 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, + 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, + }, + .oobfree = { + {.offset = 2, .length = 4, }, + {.offset = 16, .length = 6, }, + {.offset = 32, .length = 6, }, + {.offset = 48, .length = 6, }, + }, +#elif defined(CONFIG_SYS_NAND_PAGE_4K) + .eccbytes = 80, + .eccpos = { + 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, + 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, + 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, + 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, + 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, + 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, + }, + .oobfree = { + {.offset = 2, .length = 4, }, + {.offset = 16, .length = 6, }, + {.offset = 32, .length = 6, }, + {.offset = 48, .length = 6, }, + {.offset = 64, .length = 6, }, + {.offset = 80, .length = 6, }, + {.offset = 96, .length = 6, }, + {.offset = 112, .length = 6, }, + }, +#endif +}; + +#ifdef CONFIG_SYS_NAND_PAGE_2K +#define CONFIG_KEYSTONE_NAND_MAX_RBL_PAGE CONFIG_KEYSTONE_NAND_MAX_RBL_SIZE >> 11 +#elif defined(CONFIG_SYS_NAND_PAGE_4K) +#define CONFIG_KEYSTONE_NAND_MAX_RBL_PAGE CONFIG_KEYSTONE_NAND_MAX_RBL_SIZE >> 12 +#endif + +/** + * nand_davinci_write_page - write one page + * @mtd: MTD device structure + * @chip: NAND chip descriptor + * @buf: the data to write + * @oob_required: must write chip->oob_poi to OOB + * @page: page number to write + * @cached: cached programming + * @raw: use _raw version of write_page + */ +static int nand_davinci_write_page(struct mtd_info *mtd, struct nand_chip *chip, + const uint8_t *buf, int oob_required, + int page, int cached, int raw) +{ + int status; + int ret = 0; + struct nand_ecclayout *saved_ecc_layout; + + /* save current ECC layout and assign Keystone RBL ECC layout */ + if (page < CONFIG_KEYSTONE_NAND_MAX_RBL_PAGE) { + saved_ecc_layout = chip->ecc.layout; + chip->ecc.layout = &nand_keystone_rbl_4bit_layout_oobfirst; + mtd->oobavail = chip->ecc.layout->oobavail; + } + + chip->cmdfunc(mtd, NAND_CMD_SEQIN, 0x00, page); + + if (unlikely(raw)) + status = chip->ecc.write_page_raw(mtd, chip, buf, oob_required); + else + status = chip->ecc.write_page(mtd, chip, buf, oob_required); + + if (status < 0) { + ret = status; + goto err; + } + + chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1); + status = chip->waitfunc(mtd, chip); + + /* + * See if operation failed and additional status checks are + * available. + */ + if ((status & NAND_STATUS_FAIL) && (chip->errstat)) + status = chip->errstat(mtd, chip, FL_WRITING, status, page); + + if (status & NAND_STATUS_FAIL) { + ret = -EIO; + goto err; + } + +#ifdef CONFIG_MTD_NAND_VERIFY_WRITE + /* Send command to read back the data */ + chip->cmdfunc(mtd, NAND_CMD_READ0, 0, page); + + if (chip->verify_buf(mtd, buf, mtd->writesize)) { + ret = -EIO; + goto err; + } + + /* Make sure the next page prog is preceded by a status read */ + chip->cmdfunc(mtd, NAND_CMD_STATUS, -1, -1); +#endif +err: + /* restore ECC layout */ + if (page < CONFIG_KEYSTONE_NAND_MAX_RBL_PAGE) { + chip->ecc.layout = saved_ecc_layout; + mtd->oobavail = saved_ecc_layout->oobavail; + } + + return ret; +} + +/** + * nand_davinci_read_page_hwecc - hardware ECC based page read function + * @mtd: mtd info structure + * @chip: nand chip info structure + * @buf: buffer to store read data + * @oob_required: caller requires OOB data read to chip->oob_poi + * @page: page number to read + * + * Not for syndrome calculating ECC controllers which need a special oob layout. + */ +static int nand_davinci_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, + uint8_t *buf, int oob_required, int page) +{ + int i, eccsize = chip->ecc.size; + int eccbytes = chip->ecc.bytes; + int eccsteps = chip->ecc.steps; + uint32_t *eccpos; + uint8_t *p = buf; + uint8_t *ecc_code = chip->buffers->ecccode; + uint8_t *ecc_calc = chip->buffers->ecccalc; + struct nand_ecclayout *saved_ecc_layout = chip->ecc.layout; + + /* save current ECC layout and assign Keystone RBL ECC layout */ + if (page < CONFIG_KEYSTONE_NAND_MAX_RBL_PAGE) { + chip->ecc.layout = &nand_keystone_rbl_4bit_layout_oobfirst; + mtd->oobavail = chip->ecc.layout->oobavail; + } + + eccpos = chip->ecc.layout->eccpos; + + /* Read the OOB area first */ + chip->cmdfunc(mtd, NAND_CMD_READOOB, 0, page); + chip->read_buf(mtd, chip->oob_poi, mtd->oobsize); + chip->cmdfunc(mtd, NAND_CMD_READ0, 0, page); + + for (i = 0; i < chip->ecc.total; i++) + ecc_code[i] = chip->oob_poi[eccpos[i]]; + + for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) { + int stat; + + chip->ecc.hwctl(mtd, NAND_ECC_READ); + chip->read_buf(mtd, p, eccsize); + chip->ecc.calculate(mtd, p, &ecc_calc[i]); + + stat = chip->ecc.correct(mtd, p, &ecc_code[i], NULL); + if (stat < 0) + mtd->ecc_stats.failed++; + else + mtd->ecc_stats.corrected += stat; + } + + /* restore ECC layout */ + if (page < CONFIG_KEYSTONE_NAND_MAX_RBL_PAGE) { + chip->ecc.layout = saved_ecc_layout; + mtd->oobavail = saved_ecc_layout->oobavail; + } + + return 0; +} +#endif /* CONFIG_KEYSTONE_RBL_NAND */ + static void nand_davinci_4bit_enable_hwecc(struct mtd_info *mtd, int mode) { u32 val; @@ -604,6 +787,19 @@ static void nand_flash_init(void) void davinci_nand_init(struct nand_chip *nand) { +#if defined CONFIG_KEYSTONE_RBL_NAND + int i; + struct nand_ecclayout *layout; + + layout = &nand_keystone_rbl_4bit_layout_oobfirst; + layout->oobavail = 0; + for (i = 0; layout->oobfree[i].length && + i < ARRAY_SIZE(layout->oobfree); i++) + layout->oobavail += layout->oobfree[i].length; + + nand->write_page = nand_davinci_write_page; + nand->ecc.read_page = nand_davinci_read_page_hwecc; +#endif nand->chip_delay = 0; #ifdef CONFIG_SYS_NAND_USE_FLASH_BBT nand->bbt_options |= NAND_BBT_USE_FLASH; diff --git a/drivers/net/Makefile b/drivers/net/Makefile index 6226cb2..7cc6b6f 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -20,6 +20,7 @@ obj-$(CONFIG_DNET) += dnet.o obj-$(CONFIG_E1000) += e1000.o obj-$(CONFIG_E1000_SPI) += e1000_spi.o obj-$(CONFIG_EEPRO100) += eepro100.o +obj-$(CONFIG_SUNXI_EMAC) += sunxi_emac.o obj-$(CONFIG_ENC28J60) += enc28j60.o obj-$(CONFIG_EP93XX) += ep93xx_eth.o obj-$(CONFIG_ETHOC) += ethoc.o @@ -51,7 +52,6 @@ obj-$(CONFIG_RTL8169) += rtl8169.o obj-$(CONFIG_SH_ETHER) += sh_eth.o obj-$(CONFIG_SMC91111) += smc91111.o obj-$(CONFIG_SMC911X) += smc911x.o -obj-$(CONFIG_SUNXI_WEMAC) += sunxi_wemac.o obj-$(CONFIG_DRIVER_TI_EMAC) += davinci_emac.o obj-$(CONFIG_TSEC_ENET) += tsec.o fsl_mdio.o obj-$(CONFIG_DRIVER_TI_CPSW) += cpsw.o diff --git a/drivers/net/cpsw.c b/drivers/net/cpsw.c index bd5fba2..8ec5161 100644 --- a/drivers/net/cpsw.c +++ b/drivers/net/cpsw.c @@ -211,6 +211,8 @@ struct cpdma_chan { #define chan_read(chan, fld) __raw_readl((chan)->fld) #define chan_read_ptr(chan, fld) ((void *)__raw_readl((chan)->fld)) +#define for_active_slave(slave, priv) \ + slave = (priv)->slaves + (priv)->data.active_slave; if (slave) #define for_each_slave(slave, priv) \ for (slave = (priv)->slaves; slave != (priv)->slaves + \ (priv)->data.slaves; slave++) @@ -609,7 +611,7 @@ static int cpsw_update_link(struct cpsw_priv *priv) int link = 0; struct cpsw_slave *slave; - for_each_slave(slave, priv) + for_active_slave(slave, priv) cpsw_slave_update_link(slave, priv, &link); priv->mdio_link = readl(&mdio_regs->link); return link; @@ -785,7 +787,7 @@ static int cpsw_init(struct eth_device *dev, bd_t *bis) ALE_SECURE); cpsw_ale_add_mcast(priv, NetBcastAddr, 1 << priv->host_port); - for_each_slave(slave, priv) + for_active_slave(slave, priv) cpsw_slave_init(slave, priv); cpsw_update_link(priv); @@ -1013,7 +1015,7 @@ int cpsw_register(struct cpsw_platform_data *data) cpsw_mdio_init(dev->name, data->mdio_base, data->mdio_div); priv->bus = miiphy_get_dev_by_name(dev->name); - for_each_slave(slave, priv) + for_active_slave(slave, priv) cpsw_phy_init(dev, slave); return 1; diff --git a/drivers/net/netconsole.c b/drivers/net/netconsole.c index 65c747e..623f749 100644 --- a/drivers/net/netconsole.c +++ b/drivers/net/netconsole.c @@ -215,7 +215,7 @@ static void nc_send_packet(const char *buf, int len) } } -static int nc_start(void) +static int nc_start(struct stdio_dev *dev) { int retval; @@ -235,7 +235,7 @@ static int nc_start(void) return 0; } -static void nc_putc(char c) +static void nc_putc(struct stdio_dev *dev, char c) { if (output_recursion) return; @@ -246,7 +246,7 @@ static void nc_putc(char c) output_recursion = 0; } -static void nc_puts(const char *s) +static void nc_puts(struct stdio_dev *dev, const char *s) { int len; @@ -265,7 +265,7 @@ static void nc_puts(const char *s) output_recursion = 0; } -static int nc_getc(void) +static int nc_getc(struct stdio_dev *dev) { uchar c; @@ -286,7 +286,7 @@ static int nc_getc(void) return c; } -static int nc_tstc(void) +static int nc_tstc(struct stdio_dev *dev) { struct eth_device *eth; diff --git a/drivers/net/sh_eth.c b/drivers/net/sh_eth.c index 81e8ddb..451c33e 100644 --- a/drivers/net/sh_eth.c +++ b/drivers/net/sh_eth.c @@ -413,7 +413,8 @@ static int sh_eth_config(struct sh_eth_dev *eth, bd_t *bd) #if defined(CONFIG_CPU_SH7734) || defined(CONFIG_R8A7740) sh_eth_write(eth, CONFIG_SH_ETHER_SH7734_MII, RMII_MII); -#elif defined(CONFIG_R8A7790) || defined(CONFIG_R8A7791) +#elif defined(CONFIG_R8A7790) || defined(CONFIG_R8A7791) || \ + defined(CONFIG_R8A7794) sh_eth_write(eth, sh_eth_read(eth, RMIIMR) | 0x1, RMIIMR); #endif /* Configure phy */ @@ -439,7 +440,7 @@ static int sh_eth_config(struct sh_eth_dev *eth, bd_t *bd) #elif defined(CONFIG_CPU_SH7757) || defined(CONFIG_CPU_SH7752) sh_eth_write(eth, 1, RTRATE); #elif defined(CONFIG_CPU_SH7724) || defined(CONFIG_R8A7790) || \ - defined(CONFIG_R8A7791) + defined(CONFIG_R8A7791) || defined(CONFIG_R8A7794) val = ECMR_RTM; #endif } else if (phy->speed == 10) { diff --git a/drivers/net/sh_eth.h b/drivers/net/sh_eth.h index d0d9aaa..e325a39 100644 --- a/drivers/net/sh_eth.h +++ b/drivers/net/sh_eth.h @@ -358,7 +358,8 @@ static const u16 sh_eth_offset_fast_sh4[SH_ETH_MAX_REGISTER_OFFSET] = { #elif defined(CONFIG_R8A7740) #define SH_ETH_TYPE_GETHER #define BASE_IO_ADDR 0xE9A00000 -#elif defined(CONFIG_R8A7790) || defined(CONFIG_R8A7791) +#elif defined(CONFIG_R8A7790) || defined(CONFIG_R8A7791) || \ + defined(CONFIG_R8A7794) #define SH_ETH_TYPE_ETHER #define BASE_IO_ADDR 0xEE700200 #elif defined(CONFIG_R7S72100) @@ -569,7 +570,8 @@ enum FELIC_MODE_BIT { ECMR_PRM = 0x00000001, #ifdef CONFIG_CPU_SH7724 ECMR_RTM = 0x00000010, -#elif defined(CONFIG_R8A7790) || defined(CONFIG_R8A7791) +#elif defined(CONFIG_R8A7790) || defined(CONFIG_R8A7791) || \ + defined(CONFIG_R8A7794) ECMR_RTM = 0x00000004, #endif diff --git a/drivers/net/sunxi_wemac.c b/drivers/net/sunxi_emac.c index 699a381..5a06d68 100644 --- a/drivers/net/sunxi_wemac.c +++ b/drivers/net/sunxi_emac.c @@ -1,5 +1,5 @@ /* - * sunxi_wemac.c -- Allwinner A10 ethernet driver + * sunxi_emac.c -- Allwinner A10 ethernet driver * * (C) Copyright 2012, Stefan Roese <sr@denx.de> * @@ -7,16 +7,16 @@ */ #include <common.h> +#include <linux/err.h> #include <malloc.h> -#include <net.h> #include <miiphy.h> -#include <linux/err.h> +#include <net.h> #include <asm/io.h> #include <asm/arch/clock.h> #include <asm/arch/gpio.h> /* EMAC register */ -struct wemac_regs { +struct emac_regs { u32 ctl; /* 0x00 */ u32 tx_mode; /* 0x04 */ u32 tx_flow; /* 0x08 */ @@ -27,7 +27,7 @@ struct wemac_regs { u32 tx_pl1; /* 0x1c */ u32 tx_sta; /* 0x20 */ u32 tx_io_data; /* 0x24 */ - u32 tx_io_data1; /* 0x28 */ + u32 tx_io_data1;/* 0x28 */ u32 tx_tsvl0; /* 0x2c */ u32 tx_tsvh0; /* 0x30 */ u32 tx_tsvl1; /* 0x34 */ @@ -141,33 +141,33 @@ struct sunxi_sramc_regs { #define EMAC_MAC_IPGT 0x15 -#define EMAC_MAC_NBTB_IPG1 0xC +#define EMAC_MAC_NBTB_IPG1 0xc #define EMAC_MAC_NBTB_IPG2 0x12 #define EMAC_MAC_CW 0x37 -#define EMAC_MAC_RM 0xF +#define EMAC_MAC_RM 0xf #define EMAC_MAC_MFL 0x0600 /* Receive status */ -#define EMAC_CRCERR (1 << 4) -#define EMAC_LENERR (3 << 5) +#define EMAC_CRCERR (0x1 << 4) +#define EMAC_LENERR (0x3 << 5) #define DMA_CPU_TRRESHOLD 2000 -struct wemac_eth_dev { +struct emac_eth_dev { u32 speed; u32 duplex; u32 phy_configured; int link_printed; }; -struct wemac_rxhdr { +struct emac_rxhdr { s16 rx_len; u16 rx_status; }; -static void wemac_inblk_32bit(void *reg, void *data, int count) +static void emac_inblk_32bit(void *reg, void *data, int count) { int cnt = (count + 3) >> 2; @@ -181,7 +181,7 @@ static void wemac_inblk_32bit(void *reg, void *data, int count) } } -static void wemac_outblk_32bit(void *reg, void *data, int count) +static void emac_outblk_32bit(void *reg, void *data, int count) { int cnt = (count + 3) >> 2; @@ -194,14 +194,12 @@ static void wemac_outblk_32bit(void *reg, void *data, int count) } } -/* - * Read a word from phyxcer - */ -static int wemac_phy_read(const char *devname, unsigned char addr, +/* Read a word from phyxcer */ +static int emac_phy_read(const char *devname, unsigned char addr, unsigned char reg, unsigned short *value) { struct eth_device *dev = eth_get_dev_by_name(devname); - struct wemac_regs *regs = (struct wemac_regs *)dev->iobase; + struct emac_regs *regs = (struct emac_regs *)dev->iobase; /* issue the phy address and reg */ writel(addr << 8 | reg, ®s->mac_madr); @@ -221,14 +219,12 @@ static int wemac_phy_read(const char *devname, unsigned char addr, return 0; } -/* - * Write a word to phyxcer - */ -static int wemac_phy_write(const char *devname, unsigned char addr, +/* Write a word to phyxcer */ +static int emac_phy_write(const char *devname, unsigned char addr, unsigned char reg, unsigned short value) { struct eth_device *dev = eth_get_dev_by_name(devname); - struct wemac_regs *regs = (struct wemac_regs *)dev->iobase; + struct emac_regs *regs = (struct emac_regs *)dev->iobase; /* issue the phy address and reg */ writel(addr << 8 | reg, ®s->mac_madr); @@ -250,7 +246,7 @@ static int wemac_phy_write(const char *devname, unsigned char addr, static void emac_setup(struct eth_device *dev) { - struct wemac_regs *regs = (struct wemac_regs *)dev->iobase; + struct emac_regs *regs = (struct emac_regs *)dev->iobase; u32 reg_val; u16 phy_val; u32 duplex_flag; @@ -266,7 +262,7 @@ static void emac_setup(struct eth_device *dev) writel(EMAC_MAC_CTL0_SETUP, ®s->mac_ctl0); /* Set MAC CTL1 */ - wemac_phy_read(dev->name, 1, 0, &phy_val); + emac_phy_read(dev->name, 1, 0, &phy_val); debug("PHY SETUP, reg 0 value: %x\n", phy_val); duplex_flag = !!(phy_val & (1 << 8)); @@ -288,9 +284,9 @@ static void emac_setup(struct eth_device *dev) writel(EMAC_MAC_MFL, ®s->mac_maxf); } -static void wemac_reset(struct eth_device *dev) +static void emac_reset(struct eth_device *dev) { - struct wemac_regs *regs = (struct wemac_regs *)dev->iobase; + struct emac_regs *regs = (struct emac_regs *)dev->iobase; debug("resetting device\n"); @@ -302,10 +298,10 @@ static void wemac_reset(struct eth_device *dev) udelay(200); } -static int sunxi_wemac_eth_init(struct eth_device *dev, bd_t *bd) +static int sunxi_emac_eth_init(struct eth_device *dev, bd_t *bd) { - struct wemac_regs *regs = (struct wemac_regs *)dev->iobase; - struct wemac_eth_dev *priv = dev->priv; + struct emac_regs *regs = (struct emac_regs *)dev->iobase; + struct emac_eth_dev *priv = dev->priv; u16 phy_reg; /* Init EMAC */ @@ -317,10 +313,7 @@ static int sunxi_wemac_eth_init(struct eth_device *dev, bd_t *bd) /* Init MAC */ /* Soft reset MAC */ - clrbits_le32(®s->mac_ctl0, 1 << 15); - - /* Set MII clock */ - clrsetbits_le32(®s->mac_mcfg, 0xf << 2, 0xd << 2); + clrbits_le32(®s->mac_ctl0, 0x1 << 15); /* Clear RX counter */ writel(0x0, ®s->rx_fbc); @@ -336,14 +329,14 @@ static int sunxi_wemac_eth_init(struct eth_device *dev, bd_t *bd) mdelay(1); - wemac_reset(dev); + emac_reset(dev); /* PHY POWER UP */ - wemac_phy_read(dev->name, 1, 0, &phy_reg); - wemac_phy_write(dev->name, 1, 0, phy_reg & (~(1 << 11))); + emac_phy_read(dev->name, 1, 0, &phy_reg); + emac_phy_write(dev->name, 1, 0, phy_reg & (~(0x1 << 11))); mdelay(1); - wemac_phy_read(dev->name, 1, 0, &phy_reg); + emac_phy_read(dev->name, 1, 0, &phy_reg); priv->speed = miiphy_speed(dev->name, 0); priv->duplex = miiphy_duplex(dev->name, 0); @@ -357,11 +350,11 @@ static int sunxi_wemac_eth_init(struct eth_device *dev, bd_t *bd) /* Set EMAC SPEED depend on PHY */ clrsetbits_le32(®s->mac_supp, 1 << 8, - ((phy_reg & (1 << 13)) >> 13) << 8); + ((phy_reg & (0x1 << 13)) >> 13) << 8); /* Set duplex depend on phy */ clrsetbits_le32(®s->mac_ctl1, 1 << 0, - ((phy_reg & (1 << 8)) >> 8) << 0); + ((phy_reg & (0x1 << 8)) >> 8) << 0); /* Enable RX/TX */ setbits_le32(®s->ctl, 0x7); @@ -369,15 +362,15 @@ static int sunxi_wemac_eth_init(struct eth_device *dev, bd_t *bd) return 0; } -static void sunxi_wemac_eth_halt(struct eth_device *dev) +static void sunxi_emac_eth_halt(struct eth_device *dev) { /* Nothing to do here */ } -static int sunxi_wemac_eth_recv(struct eth_device *dev) +static int sunxi_emac_eth_recv(struct eth_device *dev) { - struct wemac_regs *regs = (struct wemac_regs *)dev->iobase; - struct wemac_rxhdr rxhdr; + struct emac_regs *regs = (struct emac_regs *)dev->iobase; + struct emac_rxhdr rxhdr; u32 rxcount; u32 reg_val; int rx_len; @@ -386,8 +379,7 @@ static int sunxi_wemac_eth_recv(struct eth_device *dev) /* Check packet ready or not */ - /* - * Race warning: The first packet might arrive with + /* Race warning: The first packet might arrive with * the interrupts disabled, but the second will fix */ rxcount = readl(®s->rx_fbc); @@ -401,26 +393,25 @@ static int sunxi_wemac_eth_recv(struct eth_device *dev) reg_val = readl(®s->rx_io_data); if (reg_val != 0x0143414d) { /* Disable RX */ - clrbits_le32(®s->ctl, 1 << 2); + clrbits_le32(®s->ctl, 0x1 << 2); /* Flush RX FIFO */ - setbits_le32(®s->rx_ctl, 1 << 3); - while (readl(®s->rx_ctl) & (1 << 3)) + setbits_le32(®s->rx_ctl, 0x1 << 3); + while (readl(®s->rx_ctl) & (0x1 << 3)) ; /* Enable RX */ - setbits_le32(®s->ctl, 1 << 2); + setbits_le32(®s->ctl, 0x1 << 2); return 0; } - /* - * A packet ready now + /* A packet ready now * Get status/length */ good_packet = 1; - wemac_inblk_32bit(®s->rx_io_data, &rxhdr, sizeof(rxhdr)); + emac_inblk_32bit(®s->rx_io_data, &rxhdr, sizeof(rxhdr)); rx_len = rxhdr.rx_len; rx_status = rxhdr.rx_status; @@ -440,13 +431,13 @@ static int sunxi_wemac_eth_recv(struct eth_device *dev) printf("length error\n"); } - /* Move data from WEMAC */ + /* Move data from EMAC */ if (good_packet) { if (rx_len > DMA_CPU_TRRESHOLD) { printf("Received packet is too big (len=%d)\n", rx_len); } else { - wemac_inblk_32bit((void *)®s->rx_io_data, - NetRxPackets[0], rx_len); + emac_inblk_32bit((void *)®s->rx_io_data, + NetRxPackets[0], rx_len); /* Pass to upper layer */ NetReceive(NetRxPackets[0], rx_len); @@ -457,15 +448,15 @@ static int sunxi_wemac_eth_recv(struct eth_device *dev) return 0; } -static int sunxi_wemac_eth_send(struct eth_device *dev, void *packet, int len) +static int sunxi_emac_eth_send(struct eth_device *dev, void *packet, int len) { - struct wemac_regs *regs = (struct wemac_regs *)dev->iobase; + struct emac_regs *regs = (struct emac_regs *)dev->iobase; /* Select channel 0 */ writel(0, ®s->tx_ins); /* Write packet */ - wemac_outblk_32bit((void *)®s->tx_io_data, packet, len); + emac_outblk_32bit((void *)®s->tx_io_data, packet, len); /* Set TX len */ writel(len, ®s->tx_pl0); @@ -476,50 +467,55 @@ static int sunxi_wemac_eth_send(struct eth_device *dev, void *packet, int len) return 0; } -int sunxi_wemac_initialize(void) +int sunxi_emac_initialize(void) { struct sunxi_ccm_reg *const ccm = (struct sunxi_ccm_reg *)SUNXI_CCM_BASE; struct sunxi_sramc_regs *sram = (struct sunxi_sramc_regs *)SUNXI_SRAMC_BASE; + struct emac_regs *regs = + (struct emac_regs *)SUNXI_EMAC_BASE; struct eth_device *dev; - struct wemac_eth_dev *priv; + struct emac_eth_dev *priv; int pin; dev = malloc(sizeof(*dev)); if (dev == NULL) return -ENOMEM; - priv = (struct wemac_eth_dev *)malloc(sizeof(struct wemac_eth_dev)); + priv = (struct emac_eth_dev *)malloc(sizeof(struct emac_eth_dev)); if (!priv) { free(dev); return -ENOMEM; } memset(dev, 0, sizeof(*dev)); - memset(priv, 0, sizeof(struct wemac_eth_dev)); + memset(priv, 0, sizeof(struct emac_eth_dev)); /* Map SRAM to EMAC */ setbits_le32(&sram->ctrl1, 0x5 << 2); /* Configure pin mux settings for MII Ethernet */ for (pin = SUNXI_GPA(0); pin <= SUNXI_GPA(17); pin++) - sunxi_gpio_set_cfgpin(pin, 2); + sunxi_gpio_set_cfgpin(pin, SUNXI_GPA0_EMAC); /* Set up clock gating */ - setbits_le32(&ccm->ahb_gate0, 1 << AHB_GATE_OFFSET_EMAC); + setbits_le32(&ccm->ahb_gate0, 0x1 << AHB_GATE_OFFSET_EMAC); + + /* Set MII clock */ + clrsetbits_le32(®s->mac_mcfg, 0xf << 2, 0xd << 2); - dev->iobase = SUNXI_EMAC_BASE; + dev->iobase = (int)regs; dev->priv = priv; - dev->init = sunxi_wemac_eth_init; - dev->halt = sunxi_wemac_eth_halt; - dev->send = sunxi_wemac_eth_send; - dev->recv = sunxi_wemac_eth_recv; - strcpy(dev->name, "wemac"); + dev->init = sunxi_emac_eth_init; + dev->halt = sunxi_emac_eth_halt; + dev->send = sunxi_emac_eth_send; + dev->recv = sunxi_emac_eth_recv; + strcpy(dev->name, "emac"); eth_register(dev); - miiphy_register(dev->name, wemac_phy_read, wemac_phy_write); + miiphy_register(dev->name, emac_phy_read, emac_phy_write); return 0; } diff --git a/drivers/power/Makefile b/drivers/power/Makefile index 53ff97d..dc64e4d 100644 --- a/drivers/power/Makefile +++ b/drivers/power/Makefile @@ -5,6 +5,8 @@ # SPDX-License-Identifier: GPL-2.0+ # +obj-$(CONFIG_AXP152_POWER) += axp152.o +obj-$(CONFIG_AXP209_POWER) += axp209.o obj-$(CONFIG_EXYNOS_TMU) += exynos-tmu.o obj-$(CONFIG_FTPMU010_POWER) += ftpmu010.o obj-$(CONFIG_TPS6586X_POWER) += tps6586x.o diff --git a/drivers/power/axp152.c b/drivers/power/axp152.c new file mode 100644 index 0000000..fa4ea05 --- /dev/null +++ b/drivers/power/axp152.c @@ -0,0 +1,97 @@ +/* + * (C) Copyright 2012 + * Henrik Nordstrom <henrik@henriknordstrom.net> + * + * SPDX-License-Identifier: GPL-2.0+ + */ +#include <common.h> +#include <i2c.h> +#include <axp152.h> + +enum axp152_reg { + AXP152_CHIP_VERSION = 0x3, + AXP152_DCDC2_VOLTAGE = 0x23, + AXP152_DCDC3_VOLTAGE = 0x27, + AXP152_DCDC4_VOLTAGE = 0x2B, + AXP152_LDO2_VOLTAGE = 0x2A, + AXP152_SHUTDOWN = 0x32, +}; + +#define AXP152_POWEROFF (1 << 7) + +static int axp152_write(enum axp152_reg reg, u8 val) +{ + return i2c_write(0x30, reg, 1, &val, 1); +} + +static int axp152_read(enum axp152_reg reg, u8 *val) +{ + return i2c_read(0x30, reg, 1, val, 1); +} + +static u8 axp152_mvolt_to_target(int mvolt, int min, int max, int div) +{ + if (mvolt < min) + mvolt = min; + else if (mvolt > max) + mvolt = max; + + return (mvolt - min) / div; +} + +int axp152_set_dcdc2(int mvolt) +{ + int rc; + u8 current, target; + + target = axp152_mvolt_to_target(mvolt, 700, 2275, 25); + + /* Do we really need to be this gentle? It has built-in voltage slope */ + while ((rc = axp152_read(AXP152_DCDC2_VOLTAGE, ¤t)) == 0 && + current != target) { + if (current < target) + current++; + else + current--; + rc = axp152_write(AXP152_DCDC2_VOLTAGE, current); + if (rc) + break; + } + return rc; +} + +int axp152_set_dcdc3(int mvolt) +{ + u8 target = axp152_mvolt_to_target(mvolt, 700, 3500, 25); + + return axp152_write(AXP152_DCDC3_VOLTAGE, target); +} + +int axp152_set_dcdc4(int mvolt) +{ + u8 target = axp152_mvolt_to_target(mvolt, 700, 3500, 25); + + return axp152_write(AXP152_DCDC4_VOLTAGE, target); +} + +int axp152_set_ldo2(int mvolt) +{ + u8 target = axp152_mvolt_to_target(mvolt, 700, 3500, 100); + + return axp152_write(AXP152_LDO2_VOLTAGE, target); +} + +int axp152_init(void) +{ + u8 ver; + int rc; + + rc = axp152_read(AXP152_CHIP_VERSION, &ver); + if (rc) + return rc; + + if (ver != 0x05) + return -1; + + return 0; +} diff --git a/drivers/power/axp209.c b/drivers/power/axp209.c new file mode 100644 index 0000000..9798e5b --- /dev/null +++ b/drivers/power/axp209.c @@ -0,0 +1,167 @@ +/* + * (C) Copyright 2012 + * Henrik Nordstrom <henrik@henriknordstrom.net> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <i2c.h> +#include <axp209.h> + +enum axp209_reg { + AXP209_POWER_STATUS = 0x00, + AXP209_CHIP_VERSION = 0x03, + AXP209_DCDC2_VOLTAGE = 0x23, + AXP209_DCDC3_VOLTAGE = 0x27, + AXP209_LDO24_VOLTAGE = 0x28, + AXP209_LDO3_VOLTAGE = 0x29, + AXP209_IRQ_STATUS5 = 0x4c, + AXP209_SHUTDOWN = 0x32, +}; + +#define AXP209_POWER_STATUS_ON_BY_DC (1 << 0) + +#define AXP209_IRQ5_PEK_UP (1 << 6) +#define AXP209_IRQ5_PEK_DOWN (1 << 5) + +#define AXP209_POWEROFF (1 << 7) + +static int axp209_write(enum axp209_reg reg, u8 val) +{ + return i2c_write(0x34, reg, 1, &val, 1); +} + +static int axp209_read(enum axp209_reg reg, u8 *val) +{ + return i2c_read(0x34, reg, 1, val, 1); +} + +static u8 axp209_mvolt_to_cfg(int mvolt, int min, int max, int div) +{ + if (mvolt < min) + mvolt = min; + else if (mvolt > max) + mvolt = max; + + return (mvolt - min) / div; +} + +int axp209_set_dcdc2(int mvolt) +{ + int rc; + u8 cfg, current; + + cfg = axp209_mvolt_to_cfg(mvolt, 700, 2275, 25); + + /* Do we really need to be this gentle? It has built-in voltage slope */ + while ((rc = axp209_read(AXP209_DCDC2_VOLTAGE, ¤t)) == 0 && + current != cfg) { + if (current < cfg) + current++; + else + current--; + + rc = axp209_write(AXP209_DCDC2_VOLTAGE, current); + if (rc) + break; + } + + return rc; +} + +int axp209_set_dcdc3(int mvolt) +{ + u8 cfg = axp209_mvolt_to_cfg(mvolt, 700, 3500, 25); + + return axp209_write(AXP209_DCDC3_VOLTAGE, cfg); +} + +int axp209_set_ldo2(int mvolt) +{ + int rc; + u8 cfg, reg; + + cfg = axp209_mvolt_to_cfg(mvolt, 1800, 3300, 100); + + rc = axp209_read(AXP209_LDO24_VOLTAGE, ®); + if (rc) + return rc; + + /* LDO2 configuration is in upper 4 bits */ + reg = (reg & 0x0f) | (cfg << 4); + return axp209_write(AXP209_LDO24_VOLTAGE, reg); +} + +int axp209_set_ldo3(int mvolt) +{ + u8 cfg; + + if (mvolt == -1) + cfg = 0x80; /* determined by LDO3IN pin */ + else + cfg = axp209_mvolt_to_cfg(mvolt, 700, 2275, 25); + + return axp209_write(AXP209_LDO3_VOLTAGE, cfg); +} + +int axp209_set_ldo4(int mvolt) +{ + int rc; + static const int vindex[] = { + 1250, 1300, 1400, 1500, 1600, 1700, 1800, 1900, 2000, 2500, + 2700, 2800, 3000, 3100, 3200, 3300 + }; + u8 cfg, reg; + + /* Translate mvolt to register cfg value, requested <= selected */ + for (cfg = 15; vindex[cfg] > mvolt && cfg > 0; cfg--); + + rc = axp209_read(AXP209_LDO24_VOLTAGE, ®); + if (rc) + return rc; + + /* LDO4 configuration is in lower 4 bits */ + reg = (reg & 0xf0) | (cfg << 0); + return axp209_write(AXP209_LDO24_VOLTAGE, reg); +} + +int axp209_init(void) +{ + u8 ver; + int rc; + + rc = axp209_read(AXP209_CHIP_VERSION, &ver); + if (rc) + return rc; + + /* Low 4 bits is chip version */ + ver &= 0x0f; + + if (ver != 0x1) + return -1; + + return 0; +} + +int axp209_poweron_by_dc(void) +{ + u8 v; + + if (axp209_read(AXP209_POWER_STATUS, &v)) + return 0; + + return (v & AXP209_POWER_STATUS_ON_BY_DC); +} + +int axp209_power_button(void) +{ + u8 v; + + if (axp209_read(AXP209_IRQ_STATUS5, &v)) + return 0; + + axp209_write(AXP209_IRQ_STATUS5, AXP209_IRQ5_PEK_DOWN); + + return v & AXP209_IRQ5_PEK_DOWN; +} diff --git a/drivers/power/pmic/pmic_tps65218.c b/drivers/power/pmic/pmic_tps65218.c index 0952456..dbc7a73 100644 --- a/drivers/power/pmic/pmic_tps65218.c +++ b/drivers/power/pmic/pmic_tps65218.c @@ -7,6 +7,8 @@ #include <common.h> #include <i2c.h> +#include <asm/errno.h> +#include <power/pmic.h> #include <power/tps65218.h> /** @@ -95,3 +97,23 @@ int tps65218_voltage_update(uchar dc_cntrl_reg, uchar volt_sel) return 0; } + +int power_tps65218_init(unsigned char bus) +{ + static const char name[] = "TPS65218_PMIC"; + struct pmic *p = pmic_alloc(); + + if (!p) { + printf("%s: POWER allocation error!\n", __func__); + return -ENOMEM; + } + + p->name = name; + p->interface = PMIC_I2C; + p->number_of_regs = TPS65218_PMIC_NUM_OF_REGS; + p->hw.i2c.addr = TPS65218_CHIP_PM; + p->hw.i2c.tx_num = 1; + p->bus = bus; + + return 0; +} diff --git a/drivers/serial/ns16550.c b/drivers/serial/ns16550.c index f26979d..8e7052d 100644 --- a/drivers/serial/ns16550.c +++ b/drivers/serial/ns16550.c @@ -30,7 +30,7 @@ #define serial_in(y) readb(y) #endif -#if defined(CONFIG_K2HK_EVM) +#if defined(CONFIG_SOC_KEYSTONE) #define UART_REG_VAL_PWREMU_MGMT_UART_DISABLE 0 #define UART_REG_VAL_PWREMU_MGMT_UART_ENABLE ((1 << 14) | (1 << 13) | (1 << 0)) #undef UART_MCRVAL @@ -88,7 +88,7 @@ void NS16550_init(NS16550_t com_port, int baud_divisor) /* /16 is proper to hit 115200 with 48MHz */ serial_out(0, &com_port->mdr1); #endif /* CONFIG_OMAP */ -#if defined(CONFIG_K2HK_EVM) +#if defined(CONFIG_SOC_KEYSTONE) serial_out(UART_REG_VAL_PWREMU_MGMT_UART_ENABLE, &com_port->regC); #endif } diff --git a/drivers/serial/serial.c b/drivers/serial/serial.c index fd61a5e..d2eb752 100644 --- a/drivers/serial/serial.c +++ b/drivers/serial/serial.c @@ -254,6 +254,48 @@ void serial_initialize(void) serial_assign(default_serial_console()->name); } +int serial_stub_start(struct stdio_dev *sdev) +{ + struct serial_device *dev = sdev->priv; + + return dev->start(); +} + +int serial_stub_stop(struct stdio_dev *sdev) +{ + struct serial_device *dev = sdev->priv; + + return dev->stop(); +} + +void serial_stub_putc(struct stdio_dev *sdev, const char ch) +{ + struct serial_device *dev = sdev->priv; + + dev->putc(ch); +} + +void serial_stub_puts(struct stdio_dev *sdev, const char *str) +{ + struct serial_device *dev = sdev->priv; + + dev->puts(str); +} + +int serial_stub_getc(struct stdio_dev *sdev) +{ + struct serial_device *dev = sdev->priv; + + return dev->getc(); +} + +int serial_stub_tstc(struct stdio_dev *sdev) +{ + struct serial_device *dev = sdev->priv; + + return dev->tstc(); +} + /** * serial_stdio_init() - Register serial ports with STDIO core * @@ -272,12 +314,12 @@ void serial_stdio_init(void) strcpy(dev.name, s->name); dev.flags = DEV_FLAGS_OUTPUT | DEV_FLAGS_INPUT; - dev.start = s->start; - dev.stop = s->stop; - dev.putc = s->putc; - dev.puts = s->puts; - dev.getc = s->getc; - dev.tstc = s->tstc; + dev.start = serial_stub_start; + dev.stop = serial_stub_stop; + dev.putc = serial_stub_putc; + dev.puts = serial_stub_puts; + dev.getc = serial_stub_getc; + dev.tstc = serial_stub_tstc; stdio_register(&dev); @@ -376,6 +418,7 @@ static struct serial_device *get_current(void) */ int serial_init(void) { + gd->flags |= GD_FLG_SERIAL_READY; return get_current()->start(); } diff --git a/drivers/serial/serial_ns16550.c b/drivers/serial/serial_ns16550.c index ba68d46..4413e69 100644 --- a/drivers/serial/serial_ns16550.c +++ b/drivers/serial/serial_ns16550.c @@ -120,6 +120,8 @@ static NS16550_t serial_ports[6] = { static int calc_divisor (NS16550_t port) { + const unsigned int mode_x_div = 16; + #ifdef CONFIG_OMAP1510 /* If can't cleanly clock 115200 set div to 1 */ if ((CONFIG_SYS_NS16550_CLK == 12000000) && (gd->baudrate == 115200)) { @@ -128,21 +130,9 @@ static int calc_divisor (NS16550_t port) } port->osc_12m_sel = 0; /* clear if previsouly set */ #endif -#ifdef CONFIG_OMAP1610 - /* If can't cleanly clock 115200 set div to 1 */ - if ((CONFIG_SYS_NS16550_CLK == 48000000) && (gd->baudrate == 115200)) { - return (26); /* return 26 for base divisor */ - } -#endif -#define MODE_X_DIV 16 - /* Compute divisor value. Normally, we should simply return: - * CONFIG_SYS_NS16550_CLK) / MODE_X_DIV / gd->baudrate - * but we need to round that value by adding 0.5. - * Rounding is especially important at high baud rates. - */ - return (CONFIG_SYS_NS16550_CLK + (gd->baudrate * (MODE_X_DIV / 2))) / - (MODE_X_DIV * gd->baudrate); + return DIV_ROUND_CLOSEST(CONFIG_SYS_NS16550_CLK, + mode_x_div * gd->baudrate); } void diff --git a/drivers/serial/serial_sh.h b/drivers/serial/serial_sh.h index f5e9854..341997c 100644 --- a/drivers/serial/serial_sh.h +++ b/drivers/serial/serial_sh.h @@ -226,7 +226,8 @@ struct uart_port { # define SCSPTR3 0xffc60020 /* 16 bit SCIF */ # define SCIF_ORER 0x0001 /* Overrun error bit */ # define SCSCR_INIT(port) 0x38 /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */ -#elif defined(CONFIG_R8A7790) || defined(CONFIG_R8A7791) +#elif defined(CONFIG_R8A7790) || defined(CONFIG_R8A7791) || \ + defined(CONFIG_R8A7794) # define SCIF_ORER 0x0001 # define SCSCR_INIT(port) 0x32 /* TIE=0,RIE=0,TE=1,RE=1,REIE=0, */ #else diff --git a/drivers/serial/usbtty.c b/drivers/serial/usbtty.c index 6b912ef..b030526 100644 --- a/drivers/serial/usbtty.c +++ b/drivers/serial/usbtty.c @@ -389,7 +389,7 @@ static void str2wide (char *str, u16 * wide) * Test whether a character is in the RX buffer */ -int usbtty_tstc (void) +int usbtty_tstc(struct stdio_dev *dev) { struct usb_endpoint_instance *endpoint = &endpoint_instance[rx_endpoint]; @@ -409,7 +409,7 @@ int usbtty_tstc (void) * written into its argument c. */ -int usbtty_getc (void) +int usbtty_getc(struct stdio_dev *dev) { char c; struct usb_endpoint_instance *endpoint = @@ -429,7 +429,7 @@ int usbtty_getc (void) /* * Output a single byte to the usb client port. */ -void usbtty_putc (const char c) +void usbtty_putc(struct stdio_dev *dev, const char c) { if (!usbtty_configured ()) return; @@ -484,7 +484,7 @@ static void __usbtty_puts (const char *str, int len) } } -void usbtty_puts (const char *str) +void usbtty_puts(struct stdio_dev *dev, const char *str) { int n; int len; diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index ceb1573..6685ed2 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -20,9 +20,7 @@ #include <asm/cache.h> #include <asm/io.h> #include <linux/list.h> - -#define upper_32_bits(n) (u32)((n) >> 32) -#define lower_32_bits(n) (u32)(n) +#include <linux/compat.h> #define MAX_EP_CTX_NUM 31 #define XHCI_ALIGNMENT 64 @@ -1121,7 +1119,7 @@ static inline void xhci_writeq(__le64 volatile *regs, const u64 val) __u32 *ptr = (__u32 *)regs; u32 val_lo = lower_32_bits(val); /* FIXME */ - u32 val_hi = 0; + u32 val_hi = upper_32_bits(val); writel(val_lo, ptr); writel(val_hi, ptr + 1); } diff --git a/drivers/video/cfb_console.c b/drivers/video/cfb_console.c index b52e9ed..9231927 100644 --- a/drivers/video/cfb_console.c +++ b/drivers/video/cfb_console.c @@ -944,7 +944,7 @@ static void parse_putc(const char c) CURSOR_SET; } -void video_putc(const char c) +void video_putc(struct stdio_dev *dev, const char c) { #ifdef CONFIG_CFB_CONSOLE_ANSI int i; @@ -1158,12 +1158,12 @@ void video_putc(const char c) flush_cache(VIDEO_FB_ADRS, VIDEO_SIZE); } -void video_puts(const char *s) +void video_puts(struct stdio_dev *dev, const char *s) { int count = strlen(s); while (count--) - video_putc(*s++); + video_putc(dev, *s++); } /* @@ -2279,8 +2279,6 @@ int drv_video_init(void) console_dev.flags = DEV_FLAGS_OUTPUT | DEV_FLAGS_SYSTEM; console_dev.putc = video_putc; /* 'putc' function */ console_dev.puts = video_puts; /* 'puts' function */ - console_dev.tstc = NULL; /* 'tstc' function */ - console_dev.getc = NULL; /* 'getc' function */ #if !defined(CONFIG_VGA_AS_SINGLE_DEVICE) /* Also init console device */ |