diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/clocksource/Kconfig | 4 | ||||
-rw-r--r-- | drivers/clocksource/Makefile | 2 | ||||
-rw-r--r-- | drivers/gpio/Kconfig | 6 | ||||
-rw-r--r-- | drivers/gpio/Makefile | 2 | ||||
-rw-r--r-- | drivers/input/gpio_keys.c | 23 | ||||
-rw-r--r-- | drivers/mci/Kconfig | 6 | ||||
-rw-r--r-- | drivers/mci/Makefile | 2 | ||||
-rw-r--r-- | drivers/mtd/nand/nand_base.c | 128 | ||||
-rw-r--r-- | drivers/mtd/nand/nand_mxs.c | 42 | ||||
-rw-r--r-- | drivers/of/Kconfig | 7 | ||||
-rw-r--r-- | drivers/of/barebox.c | 47 | ||||
-rw-r--r-- | drivers/of/of_path.c | 132 | ||||
-rw-r--r-- | drivers/pci/pci-imx6.c | 75 | ||||
-rw-r--r-- | drivers/regulator/Kconfig | 4 | ||||
-rw-r--r-- | drivers/regulator/Makefile | 2 | ||||
-rw-r--r-- | drivers/reset/core.c | 1 | ||||
-rw-r--r-- | drivers/rtc/Kconfig | 3 | ||||
-rw-r--r-- | drivers/rtc/Makefile | 1 | ||||
-rw-r--r-- | drivers/rtc/class.c | 11 | ||||
-rw-r--r-- | drivers/rtc/rtc-abracon.c | 126 | ||||
-rw-r--r-- | drivers/rtc/rtc-ds1307.c | 94 | ||||
-rw-r--r-- | drivers/rtc/rtc-lib.c | 2 | ||||
-rw-r--r-- | drivers/usb/imx/chipidea-imx.c | 3 | ||||
-rw-r--r-- | drivers/video/Kconfig | 8 | ||||
-rw-r--r-- | drivers/video/Makefile | 2 |
25 files changed, 594 insertions, 139 deletions
diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig index 598edc9a81..3fb09fbec4 100644 --- a/drivers/clocksource/Kconfig +++ b/drivers/clocksource/Kconfig @@ -6,9 +6,9 @@ config ARM_SMP_TWD bool depends on ARM && CPU_V7 -config CLOCKSOURCE_BCM2835 +config CLOCKSOURCE_BCM283X bool - depends on ARCH_BCM2835 + depends on ARCH_BCM283X config CLOCKSOURCE_CLPS711X bool diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile index f5f5141a3d..4eb1656ee0 100644 --- a/drivers/clocksource/Makefile +++ b/drivers/clocksource/Makefile @@ -1,6 +1,6 @@ obj-$(CONFIG_AMBA_SP804) += amba-sp804.o obj-$(CONFIG_ARM_SMP_TWD) += arm_smp_twd.o -obj-$(CONFIG_CLOCKSOURCE_BCM2835) += bcm2835.o +obj-$(CONFIG_CLOCKSOURCE_BCM283X) += bcm2835.o obj-$(CONFIG_CLOCKSOURCE_CLPS711X) += clps711x.o obj-$(CONFIG_CLOCKSOURCE_DIGIC) += digic.o obj-$(CONFIG_CLOCKSOURCE_MVEBU) += mvebu.o diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 9cb22613dd..d839d7a426 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -21,9 +21,9 @@ config GPIO_74164 shift registers. This driver can be used to provide access to more gpio outputs. -config GPIO_BCM2835 - bool "GPIO support for BCM2835" - depends on ARCH_BCM2835 +config GPIO_BCM283X + bool "GPIO support for BCM283X" + depends on ARCH_BCM283X config GPIO_CLPS711X bool "GPIO support for CLPS711X" diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index f39e8da6e1..8767eed1e8 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -2,7 +2,7 @@ obj-$(CONFIG_GPIOLIB) += gpiolib.o obj-$(CONFIG_GPIO_74164) += gpio-74164.o obj-$(CONFIG_MACH_MIPS_ATH79) += gpio-ath79.o -obj-$(CONFIG_GPIO_BCM2835) += gpio-bcm2835.o +obj-$(CONFIG_GPIO_BCM283X) += gpio-bcm2835.o obj-$(CONFIG_GPIO_DAVINCI) += gpio-davinci.o obj-$(CONFIG_GPIO_CLPS711X) += gpio-clps711x.o obj-$(CONFIG_GPIO_DIGIC) += gpio-digic.o diff --git a/drivers/input/gpio_keys.c b/drivers/input/gpio_keys.c index d017594662..5b03fd76cb 100644 --- a/drivers/input/gpio_keys.c +++ b/drivers/input/gpio_keys.c @@ -21,6 +21,9 @@ struct gpio_key { int active_low; int previous_state; + + int debounce_interval; + u64 debounce_start; }; struct gpio_keys { @@ -60,11 +63,17 @@ static void gpio_key_poller(struct poller_struct *poller) gb = &gk->buttons[i]; val = gpio_get_value(gb->gpio); - if (val != gb->previous_state && val != gb->active_low) { - kfifo_put(gk->recv_fifo, (u_char*)&gb->code, sizeof(int)); - debug("pressed gpio(%d) as %d\n", gb->gpio, gb->code); + if (!is_timeout(gb->debounce_start, gb->debounce_interval * MSECOND)) + continue; + + if (val != gb->previous_state) { + gb->debounce_start = get_time_ns(); + if (val != gb->active_low) { + kfifo_put(gk->recv_fifo, (u_char*)&gb->code, sizeof(int)); + debug("pressed gpio(%d) as %d\n", gb->gpio, gb->code); + } + gb->previous_state = val; } - gb->previous_state = val; } } @@ -111,6 +120,7 @@ static int gpio_keys_probe_pdata(struct gpio_keys *gk, struct device_d *dev) gk->buttons[i].gpio = pdata->buttons[i].gpio; gk->buttons[i].code = pdata->buttons[i].code; gk->buttons[i].active_low = pdata->buttons[i].active_low; + gk->buttons[i].debounce_interval = 20; } return 0; @@ -142,6 +152,11 @@ static int gpio_keys_probe_dt(struct gpio_keys *gk, struct device_d *dev) if (ret) return ret; + gk->buttons[i].debounce_interval = 20; + + of_property_read_u32(npkey, "debounce-interval", + &gk->buttons[i].debounce_interval); + gk->buttons[i].code = keycode; i++; diff --git a/drivers/mci/Kconfig b/drivers/mci/Kconfig index ebd8da9591..0f3504c735 100644 --- a/drivers/mci/Kconfig +++ b/drivers/mci/Kconfig @@ -62,9 +62,9 @@ config MCI_S3C Enable this entry to add support to read and write SD cards on a Samsung S3C24xx based system. -config MCI_BCM2835 - bool "MCI support for BCM2835" - depends on ARCH_BCM2835 +config MCI_BCM283X + bool "MCI support for BCM283X" + depends on ARCH_BCM283X config MCI_IMX bool "i.MX" diff --git a/drivers/mci/Makefile b/drivers/mci/Makefile index 1e8443c1af..88ec456aa3 100644 --- a/drivers/mci/Makefile +++ b/drivers/mci/Makefile @@ -1,6 +1,6 @@ obj-$(CONFIG_MCI) += mci-core.o obj-$(CONFIG_MCI_ATMEL) += atmel_mci.o -obj-$(CONFIG_MCI_BCM2835) += mci-bcm2835.o +obj-$(CONFIG_MCI_BCM283X) += mci-bcm2835.o obj-$(CONFIG_MCI_IMX) += imx.o obj-$(CONFIG_MCI_IMX_ESDHC) += imx-esdhc.o obj-$(CONFIG_MCI_MXS) += mxs.o diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index ca48f59de1..554d3d2f96 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c @@ -907,6 +907,134 @@ out: EXPORT_SYMBOL(nand_lock); /** + * nand_check_erased_buf - check if a buffer contains (almost) only 0xff data + * @buf: buffer to test + * @len: buffer length + * @bitflips_threshold: maximum number of bitflips + * + * Check if a buffer contains only 0xff, which means the underlying region + * has been erased and is ready to be programmed. + * The bitflips_threshold specify the maximum number of bitflips before + * considering the region is not erased. + * Note: The logic of this function has been extracted from the memweight + * implementation, except that nand_check_erased_buf function exit before + * testing the whole buffer if the number of bitflips exceed the + * bitflips_threshold value. + * + * Returns a positive number of bitflips less than or equal to + * bitflips_threshold, or -ERROR_CODE for bitflips in excess of the + * threshold. + */ +static int nand_check_erased_buf(void *buf, int len, int bitflips_threshold) +{ + const unsigned char *bitmap = buf; + int bitflips = 0; + int weight; + + for (; len && ((uintptr_t)bitmap) % sizeof(long); + len--, bitmap++) { + weight = hweight8(*bitmap); + bitflips += BITS_PER_BYTE - weight; + if (unlikely(bitflips > bitflips_threshold)) + return -EBADMSG; + } + + for (; len >= sizeof(long); + len -= sizeof(long), bitmap += sizeof(long)) { + weight = hweight_long(*((unsigned long *)bitmap)); + bitflips += BITS_PER_LONG - weight; + if (unlikely(bitflips > bitflips_threshold)) + return -EBADMSG; + } + + for (; len > 0; len--, bitmap++) { + weight = hweight8(*bitmap); + bitflips += BITS_PER_BYTE - weight; + if (unlikely(bitflips > bitflips_threshold)) + return -EBADMSG; + } + + return bitflips; +} + +/** + * nand_check_erased_ecc_chunk - check if an ECC chunk contains (almost) only + * 0xff data + * @data: data buffer to test + * @datalen: data length + * @ecc: ECC buffer + * @ecclen: ECC length + * @extraoob: extra OOB buffer + * @extraooblen: extra OOB length + * @bitflips_threshold: maximum number of bitflips + * + * Check if a data buffer and its associated ECC and OOB data contains only + * 0xff pattern, which means the underlying region has been erased and is + * ready to be programmed. + * The bitflips_threshold specify the maximum number of bitflips before + * considering the region as not erased. + * + * Note: + * 1/ ECC algorithms are working on pre-defined block sizes which are usually + * different from the NAND page size. When fixing bitflips, ECC engines will + * report the number of errors per chunk, and the NAND core infrastructure + * expect you to return the maximum number of bitflips for the whole page. + * This is why you should always use this function on a single chunk and + * not on the whole page. After checking each chunk you should update your + * max_bitflips value accordingly. + * 2/ When checking for bitflips in erased pages you should not only check + * the payload data but also their associated ECC data, because a user might + * have programmed almost all bits to 1 but a few. In this case, we + * shouldn't consider the chunk as erased, and checking ECC bytes prevent + * this case. + * 3/ The extraoob argument is optional, and should be used if some of your OOB + * data are protected by the ECC engine. + * It could also be used if you support subpages and want to attach some + * extra OOB data to an ECC chunk. + * + * Returns a positive number of bitflips less than or equal to + * bitflips_threshold, or -ERROR_CODE for bitflips in excess of the + * threshold. In case of success, the passed buffers are filled with 0xff. + */ +int nand_check_erased_ecc_chunk(void *data, int datalen, + void *ecc, int ecclen, + void *extraoob, int extraooblen, + int bitflips_threshold) +{ + int data_bitflips = 0, ecc_bitflips = 0, extraoob_bitflips = 0; + + data_bitflips = nand_check_erased_buf(data, datalen, + bitflips_threshold); + if (data_bitflips < 0) + return data_bitflips; + + bitflips_threshold -= data_bitflips; + + ecc_bitflips = nand_check_erased_buf(ecc, ecclen, bitflips_threshold); + if (ecc_bitflips < 0) + return ecc_bitflips; + + bitflips_threshold -= ecc_bitflips; + + extraoob_bitflips = nand_check_erased_buf(extraoob, extraooblen, + bitflips_threshold); + if (extraoob_bitflips < 0) + return extraoob_bitflips; + + if (data_bitflips) + memset(data, 0xff, datalen); + + if (ecc_bitflips) + memset(ecc, 0xff, ecclen); + + if (extraoob_bitflips) + memset(extraoob, 0xff, extraooblen); + + return data_bitflips + ecc_bitflips + extraoob_bitflips; +} +EXPORT_SYMBOL(nand_check_erased_ecc_chunk); + +/** * nand_read_page_raw - [INTERN] read raw page data without ecc * @mtd: mtd info structure * @chip: nand chip info structure diff --git a/drivers/mtd/nand/nand_mxs.c b/drivers/mtd/nand/nand_mxs.c index b3767e6cbe..7635e2a418 100644 --- a/drivers/mtd/nand/nand_mxs.c +++ b/drivers/mtd/nand/nand_mxs.c @@ -737,6 +737,8 @@ static int mxs_nand_ecc_read_page(struct mtd_info *mtd, struct nand_chip *nand, /* Read DMA completed, now do the mark swapping. */ mxs_nand_swap_block_mark(mtd, nand_info->data_buf, nand_info->oob_buf); + memcpy(buf, nand_info->data_buf, mtd->writesize); + /* Loop over status bytes, accumulating ECC status. */ status = nand_info->oob_buf + mxs_nand_aux_status_offset(); for (i = 0; i < mxs_nand_ecc_chunk_cnt(mtd->writesize); i++) { @@ -747,6 +749,44 @@ static int mxs_nand_ecc_read_page(struct mtd_info *mtd, struct nand_chip *nand, continue; if (status[i] == 0xfe) { + int flips; + + /* + * The ECC hardware has an uncorrectable ECC status + * code in case we have bitflips in an erased page. As + * nothing was written into this subpage the ECC is + * obviously wrong and we can not trust it. We assume + * at this point that we are reading an erased page and + * try to correct the bitflips in buffer up to + * ecc_strength bitflips. If this is a page with random + * data, we exceed this number of bitflips and have a + * ECC failure. Otherwise we use the corrected buffer. + */ + if (i == 0) { + /* The first block includes metadata */ + flips = nand_check_erased_ecc_chunk( + buf + i * MXS_NAND_CHUNK_DATA_CHUNK_SIZE, + MXS_NAND_CHUNK_DATA_CHUNK_SIZE, + NULL, 0, + nand_info->oob_buf, + MXS_NAND_METADATA_SIZE, + mtd->ecc_strength); + } else { + flips = nand_check_erased_ecc_chunk( + buf + i * MXS_NAND_CHUNK_DATA_CHUNK_SIZE, + MXS_NAND_CHUNK_DATA_CHUNK_SIZE, + NULL, 0, + NULL, 0, + mtd->ecc_strength); + } + + if (flips > 0) { + max_bitflips = max_t(unsigned int, + max_bitflips, flips); + corrected += flips; + continue; + } + failed++; continue; } @@ -772,8 +812,6 @@ static int mxs_nand_ecc_read_page(struct mtd_info *mtd, struct nand_chip *nand, nand->oob_poi[0] = nand_info->oob_buf[0]; - memcpy(buf, nand_info->data_buf, mtd->writesize); - ret = 0; rtn: mxs_nand_return_dma_descs(nand_info); diff --git a/drivers/of/Kconfig b/drivers/of/Kconfig index 90475cfbca..d0a62bda91 100644 --- a/drivers/of/Kconfig +++ b/drivers/of/Kconfig @@ -43,3 +43,10 @@ config OF_BAREBOX_DRIVERS support for this feature. This currently allows to configure the environment path from devicetree and to partition devices. See Documentation/devicetree/bindings/barebox/ for more information. + +config OF_BAREBOX_ENV_IN_FS + depends on OF_BAREBOX_DRIVERS + bool "Allow environment to come from file" + help + Allow the devie tree configuration of the barebox environment path + to specify a file in filesystem, which will be mounted. diff --git a/drivers/of/barebox.c b/drivers/of/barebox.c index 1b3078eb47..125feef2cc 100644 --- a/drivers/of/barebox.c +++ b/drivers/of/barebox.c @@ -24,7 +24,46 @@ #include <malloc.h> #include <partition.h> #include <envfs.h> -#include <linux/mtd/mtd.h> +#include <fs.h> + +#define ENV_MNT_DIR "/boot" /* If env on filesystem, where to mount */ + +/* If dev describes a file on a fs, mount the fs and change devpath to + * point to the file's path. Otherwise leave devpath alone. Does + * nothing in env in a file support isn't enabled. */ +static int environment_check_mount(struct device_d *dev, char **devpath) +{ + const char *filepath; + int ret; + + if (!IS_ENABLED(CONFIG_OF_BAREBOX_ENV_IN_FS)) + return 0; + + ret = of_property_read_string(dev->device_node, "file-path", &filepath); + if (ret == -EINVAL) { + /* No file-path so just use device-path */ + return 0; + } else if (ret) { + /* file-path property exists, but has error */ + dev_err(dev, "Problem with file-path property\n"); + return ret; + } + + /* Get device env is on and mount it */ + mkdir(ENV_MNT_DIR, 0777); + ret = mount(*devpath, "fat", ENV_MNT_DIR, NULL); + if (ret) { + dev_err(dev, "Failed to load environment: mount %s failed (%d)\n", + *devpath, ret); + return ret; + } + + /* Set env to be in a file on the now mounted device */ + dev_dbg(dev, "Loading default env from %s on device %s\n", + filepath, *devpath); + *devpath = asprintf("%s/%s", ENV_MNT_DIR, filepath); + return 0; +} static int environment_probe(struct device_d *dev) { @@ -35,8 +74,12 @@ static int environment_probe(struct device_d *dev) if (ret) return ret; - dev_info(dev, "setting default environment path to %s\n", path); + /* Do we need to mount a fs and find env there? */ + ret = environment_check_mount(dev, &path); + if (ret) + return ret; + dev_dbg(dev, "Setting default environment path to %s\n", path); default_environment_path_set(path); return 0; diff --git a/drivers/of/of_path.c b/drivers/of/of_path.c index 6903905259..ed620f1755 100644 --- a/drivers/of/of_path.c +++ b/drivers/of/of_path.c @@ -23,16 +23,6 @@ #include <linux/mtd/mtd.h> -struct of_path { - struct cdev *cdev; - struct device_d *dev; -}; - -struct of_path_type { - const char *name; - int (*parse)(struct of_path *op, const char *str); -}; - struct device_d *of_find_device_by_node_path(const char *path) { struct device_d *dev; @@ -48,102 +38,44 @@ struct device_d *of_find_device_by_node_path(const char *path) } /** - * of_path_type_partname - find a partition based on physical device and - * partition name - * @op: of_path context - * @name: the partition name to find + * __of_find_path + * + * @node: The node to find the cdev for, can be the device or a + * partition in the device + * @part: Optionally, a description of a parition of @node. See of_find_path + * @outpath: if this function returns 0 outpath will contain the path belonging + * to the input path description. Must be freed with free(). + * @flags: use OF_FIND_PATH_FLAGS_BB to return the .bb device if available + * */ -static int of_path_type_partname(struct of_path *op, const char *name) -{ - if (!op->dev) - return -EINVAL; - - op->cdev = device_find_partition(op->dev, name); - if (op->cdev) { - pr_debug("%s: found part '%s'\n", __func__, name); - return 0; - } else { - pr_debug("%s: cannot find part '%s'\n", __func__, name); - return -ENODEV; - } -} - -static struct of_path_type of_path_types[] = { - { - .name = "partname", - .parse = of_path_type_partname, - }, -}; - -static int of_path_parse_one(struct of_path *op, const char *str) +static int __of_find_path(struct device_node *node, const char *part, char **outpath, unsigned flags) { - int i, ret; - char *name, *desc; - - pr_debug("parsing: %s\n", str); - - name = xstrdup(str); - desc = strchr(name, ':'); - if (!desc) { - free(name); - return -EINVAL; - } - - *desc = 0; - desc++; - - for (i = 0; i < ARRAY_SIZE(of_path_types); i++) { - if (!strcmp(of_path_types[i].name, name)) { - ret = of_path_types[i].parse(op, desc); - goto out; - } - } - - ret = -EINVAL; -out: - free(name); - - return ret; -} - -static int __of_find_path(struct device_node *node, const char *propname, char **outpath, unsigned flags) -{ - struct of_path op = {}; - const char *str; + struct device_d *dev; + struct cdev *cdev; bool add_bb = false; - int i, ret; - op.dev = of_find_device_by_node_path(node->full_name); - if (!op.dev) { - op.dev = of_find_device_by_node_path(node->parent->full_name); - if (!op.dev) + dev = of_find_device_by_node_path(node->full_name); + if (!dev) { + dev = of_find_device_by_node_path(node->parent->full_name); + if (!dev) return -ENODEV; } - device_detect(op.dev); - - op.cdev = cdev_by_device_node(node); + device_detect(dev); - i = 1; + if (part) + cdev = device_find_partition(dev, part); + else + cdev = cdev_by_device_node(node); - while (propname) { - ret = of_property_read_string_index(node, propname, i++, &str); - if (ret) - break; - - ret = of_path_parse_one(&op, str); - if (ret) - return ret; - } - - if (!op.cdev) + if (!cdev) return -ENOENT; - if ((flags & OF_FIND_PATH_FLAGS_BB) && op.cdev->mtd && - mtd_can_have_bb(op.cdev->mtd)) + if ((flags & OF_FIND_PATH_FLAGS_BB) && cdev->mtd && + mtd_can_have_bb(cdev->mtd)) add_bb = true; - *outpath = asprintf("/dev/%s%s", op.cdev->name, add_bb ? ".bb" : ""); + *outpath = asprintf("/dev/%s%s", cdev->name, add_bb ? ".bb" : ""); return 0; } @@ -193,6 +125,8 @@ int of_find_path(struct device_node *node, const char *propname, char **outpath, { struct device_node *rnode; const char *path; + const char *part = NULL; + const char partnamestr[] = "partname:"; path = of_get_property(node, propname, NULL); if (!path) @@ -202,5 +136,15 @@ int of_find_path(struct device_node *node, const char *propname, char **outpath, if (!rnode) return -ENODEV; - return __of_find_path(rnode, propname, outpath, flags); + of_property_read_string_index(node, propname, 1, &part); + if (part) { + if (!strncmp(part, partnamestr, sizeof(partnamestr) - 1)) { + part += sizeof(partnamestr) - 1; + } else { + pr_err("Invalid device-path: %s\n", part); + return -EINVAL; + } + } + + return __of_find_path(rnode, part, outpath, flags); } diff --git a/drivers/pci/pci-imx6.c b/drivers/pci/pci-imx6.c index eaa5f0ef58..d32bd2b4ce 100644 --- a/drivers/pci/pci-imx6.c +++ b/drivers/pci/pci-imx6.c @@ -13,6 +13,7 @@ #include <common.h> #include <clock.h> +#include <abort.h> #include <malloc.h> #include <io.h> #include <init.h> @@ -51,6 +52,8 @@ struct imx6_pcie { #define PCIE_RC_LCR_MAX_LINK_SPEEDS_GEN2 0x2 #define PCIE_RC_LCR_MAX_LINK_SPEEDS_MASK 0xf +#define PCIE_RC_LCSR 0x80 + /* PCIe Port Logic registers (memory-mapped) */ #define PL_OFFSET 0x700 #define PCIE_PL_PFLR (PL_OFFSET + 0x08) @@ -235,7 +238,10 @@ static int imx6_pcie_assert_core_reset(struct pcie_port *pp) val = readl(pp->dbi_base + PCIE_PL_PFLR); val &= ~PCIE_PL_PFLR_LINK_STATE_MASK; val |= PCIE_PL_PFLR_FORCE_LINK; + + data_abort_mask(); writel(val, pp->dbi_base + PCIE_PL_PFLR); + data_abort_unmask(); gpr12 &= ~IMX6Q_GPR12_PCIE_CTL_2; writel(gpr12, imx6_pcie->iomuxc_gpr + IOMUXC_GPR12); @@ -360,13 +366,29 @@ static int imx6_pcie_wait_for_link(struct pcie_port *pp) } } +static int imx6_pcie_wait_for_speed_change(struct pcie_port *pp) +{ + uint32_t tmp; + uint64_t start = get_time_ns(); + + while (!is_timeout(start, SECOND)) { + tmp = readl(pp->dbi_base + PCIE_LINK_WIDTH_SPEED_CONTROL); + /* Test if the speed change finished. */ + if (!(tmp & PORT_LOGIC_SPEED_CHANGE)) + return 0; + } + + dev_err(pp->dev, "Speed change timeout\n"); + return -EINVAL; +} + + static int imx6_pcie_start_link(struct pcie_port *pp) { struct imx6_pcie *imx6_pcie = to_imx6_pcie(pp); uint32_t tmp; int ret; u32 gpr12; - u64 start; /* * Force Gen1 operation when starting the link. In case the link is @@ -401,28 +423,22 @@ static int imx6_pcie_start_link(struct pcie_port *pp) tmp |= PORT_LOGIC_SPEED_CHANGE; writel(tmp, pp->dbi_base + PCIE_LINK_WIDTH_SPEED_CONTROL); - start = get_time_ns(); - while (!is_timeout(start, SECOND)) { - tmp = readl(pp->dbi_base + PCIE_LINK_WIDTH_SPEED_CONTROL); - /* Test if the speed change finished. */ - if (!(tmp & PORT_LOGIC_SPEED_CHANGE)) - break; + ret = imx6_pcie_wait_for_speed_change(pp); + if (ret) { + dev_err(pp->dev, "Failed to bring link up!\n"); + return ret; } /* Make sure link training is finished as well! */ - if (tmp & PORT_LOGIC_SPEED_CHANGE) - ret = -EINVAL; - else - ret = imx6_pcie_wait_for_link(pp); - + ret = imx6_pcie_wait_for_link(pp); if (ret) { dev_err(pp->dev, "Failed to bring link up!\n"); - } else { - tmp = readl(pp->dbi_base + 0x80); - dev_dbg(pp->dev, "Link up, Gen=%i\n", (tmp >> 16) & 0xf); + return ret; } - return ret; + tmp = readl(pp->dbi_base + PCIE_RC_LCSR); + dev_dbg(pp->dev, "Link up, Gen=%i\n", (tmp >> 16) & 0xf); + return 0; } static void imx6_pcie_host_init(struct pcie_port *pp) @@ -592,9 +608,35 @@ static int __init imx6_pcie_probe(struct device_d *dev) if (ret < 0) return ret; + dev->priv = imx6_pcie; + return 0; } +static void imx6_pcie_remove(struct device_d *dev) +{ + struct imx6_pcie *imx6_pcie = dev->priv; + u32 val; + + val = readl(imx6_pcie->pp.dbi_base + PCIE_PL_PFLR); + val &= ~PCIE_PL_PFLR_LINK_STATE_MASK; + val |= PCIE_PL_PFLR_FORCE_LINK; + data_abort_mask(); + writel(val, imx6_pcie->pp.dbi_base + PCIE_PL_PFLR); + data_abort_unmask(); + + val = readl(imx6_pcie->iomuxc_gpr + IOMUXC_GPR12); + val &= ~IMX6Q_GPR12_PCIE_CTL_2; + writel(val, imx6_pcie->iomuxc_gpr + IOMUXC_GPR12); + + val = readl(imx6_pcie->iomuxc_gpr + IOMUXC_GPR1); + val |= IMX6Q_GPR1_PCIE_TEST_PD; + writel(val, imx6_pcie->iomuxc_gpr + IOMUXC_GPR1); + + val &= ~IMX6Q_GPR1_PCIE_REF_CLK_EN; + writel(val, imx6_pcie->iomuxc_gpr + IOMUXC_GPR1); +} + static struct of_device_id imx6_pcie_of_match[] = { { .compatible = "fsl,imx6q-pcie", }, {}, @@ -604,6 +646,7 @@ static struct driver_d imx6_pcie_driver = { .name = "imx6-pcie", .of_compatible = DRV_OF_COMPAT(imx6_pcie_of_match), .probe = imx6_pcie_probe, + .remove = imx6_pcie_remove, }; device_platform_driver(imx6_pcie_driver); diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig index 05c3f48980..4b4125254f 100644 --- a/drivers/regulator/Kconfig +++ b/drivers/regulator/Kconfig @@ -11,9 +11,9 @@ config REGULATOR_FIXED This enables a simple fixed regulator. It is used for regulators which are not software controllable or controllable via gpio. -config REGULATOR_BCM2835 +config REGULATOR_BCM283X bool - depends on ARCH_BCM2835 + depends on ARCH_BCM283X default y endif diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile index d663c16b1a..a8dd9bd055 100644 --- a/drivers/regulator/Makefile +++ b/drivers/regulator/Makefile @@ -1,3 +1,3 @@ obj-$(CONFIG_REGULATOR) += core.o obj-$(CONFIG_REGULATOR_FIXED) += fixed.o -obj-$(CONFIG_REGULATOR_BCM2835) += bcm2835.o +obj-$(CONFIG_REGULATOR_BCM283X) += bcm2835.o diff --git a/drivers/reset/core.c b/drivers/reset/core.c index 0f900a92d0..59f75ca475 100644 --- a/drivers/reset/core.c +++ b/drivers/reset/core.c @@ -190,6 +190,7 @@ struct reset_control *of_reset_control_get(struct device_node *node, rstc->rcdev = rcdev; rstc->id = rstc_id; + rstc->gpio = -ENODEV; return rstc; } diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index 191ad97fb8..7d181949ee 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -33,6 +33,9 @@ config RTC_DRV_DS1307 registers may add features such as NVRAM, a trickle charger for the RTC/NVRAM backup power, and alarms. +config RTC_DRV_ABRACON + tristate "Abracon RTCs" + endif # I2C config RTC_DRV_JZ4740 diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile index 1cc9bb8b4b..68741c26a1 100644 --- a/drivers/rtc/Makefile +++ b/drivers/rtc/Makefile @@ -7,5 +7,6 @@ obj-$(CONFIG_RTC_CLASS) += class.o # Keep the list ordered. +obj-$(CONFIG_RTC_DRV_ABRACON) += rtc-abracon.o obj-$(CONFIG_RTC_DRV_DS1307) += rtc-ds1307.o obj-$(CONFIG_RTC_DRV_JZ4740) += rtc-jz4740.o diff --git a/drivers/rtc/class.c b/drivers/rtc/class.c index 356707be2f..8b047a638d 100644 --- a/drivers/rtc/class.c +++ b/drivers/rtc/class.c @@ -46,7 +46,16 @@ EXPORT_SYMBOL(rtc_read_time); int rtc_set_time(struct rtc_device *rtc, struct rtc_time *tm) { - return rtc->ops->set_time(rtc, tm); + struct rtc_time time; + unsigned long secs; + + if (rtc_valid_tm(tm)) + return -EINVAL; + + rtc_tm_to_time(tm, &secs); + rtc_time_to_tm(secs, &time); + + return rtc->ops->set_time(rtc, &time); } EXPORT_SYMBOL(rtc_set_time); diff --git a/drivers/rtc/rtc-abracon.c b/drivers/rtc/rtc-abracon.c new file mode 100644 index 0000000000..b3af990b9c --- /dev/null +++ b/drivers/rtc/rtc-abracon.c @@ -0,0 +1,126 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; version 2. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + */ + +#include <common.h> +#include <init.h> +#include <driver.h> +#include <xfuncs.h> +#include <errno.h> +#include <i2c/i2c.h> +#include <rtc.h> +#include <linux/rtc.h> +#include <linux/bcd.h> + +struct abracon { + struct rtc_device rtc; + struct i2c_client *client; +}; + +static inline struct abracon *to_abracon_priv(struct rtc_device *rtcdev) +{ + return container_of(rtcdev, struct abracon, rtc); +} + +static int abracon_get_time(struct rtc_device *rtcdev, struct rtc_time *t) +{ + struct abracon *abracon = to_abracon_priv(rtcdev); + struct i2c_client *client = abracon->client; + u8 cp[7] = {}; + u8 reg = 8; + struct i2c_msg msg[2] = {}; + int ret; + + msg[0].addr = client->addr; + msg[0].buf = ® + msg[0].len = 1; + + msg[1].addr = client->addr; + msg[1].flags = I2C_M_RD; + msg[1].buf = cp; + msg[1].len = 7; + + ret = i2c_transfer(client->adapter, msg, 2); + if (ret != 2) + return -EIO; + + t->tm_sec = bcd2bin(cp[0]); + t->tm_min = bcd2bin(cp[1]); + t->tm_hour = bcd2bin(cp[2]); + t->tm_mday = bcd2bin(cp[3]); + t->tm_wday = bcd2bin(cp[4]); + t->tm_mon = bcd2bin(cp[5]); + t->tm_year = bcd2bin(cp[6]) + 100; + + return 0; +} + +static int abracon_set_time(struct rtc_device *rtcdev, struct rtc_time *t) +{ + struct abracon *abracon = to_abracon_priv(rtcdev); + struct i2c_client *client = abracon->client; + u8 cp[8] = {}; + int ret; + + cp[0] = 8; + cp[1] = bin2bcd(t->tm_sec); + cp[2] = bin2bcd(t->tm_min); + cp[3] = bin2bcd(t->tm_hour); + cp[4] = bin2bcd(t->tm_mday); + cp[5] = bin2bcd(t->tm_wday); + cp[6] = bin2bcd(t->tm_mon); + cp[7] = bin2bcd(t->tm_year - 100); + + ret = i2c_master_send(client, cp, 8); + if (ret != 8) + return -EIO; + + return 0; +} + +static const struct rtc_class_ops ds13xx_rtc_ops = { + .read_time = abracon_get_time, + .set_time = abracon_set_time, +}; + +static int abracon_probe(struct device_d *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct abracon *abracon; + int ret; + + abracon = xzalloc(sizeof(*abracon)); + + abracon->client = client; + + abracon->rtc.ops = &ds13xx_rtc_ops; + abracon->rtc.dev = dev; + + ret = rtc_register(&abracon->rtc); + + return ret; +}; + +static struct platform_device_id abracon_id[] = { + { "ab-rtcmc-32.768khz-eoz9-s3", 0 }, + { } +}; + +static struct driver_d abracon_driver = { + .name = "rtc-abracon", + .probe = abracon_probe, + .id_table = abracon_id, +}; + +static int __init abracon_init(void) +{ + return i2c_driver_register(&abracon_driver); +} +device_initcall(abracon_init);
\ No newline at end of file diff --git a/drivers/rtc/rtc-ds1307.c b/drivers/rtc/rtc-ds1307.c index d78faa892d..e2d561b96f 100644 --- a/drivers/rtc/rtc-ds1307.c +++ b/drivers/rtc/rtc-ds1307.c @@ -17,6 +17,7 @@ #include <init.h> #include <driver.h> #include <xfuncs.h> +#include <malloc.h> #include <errno.h> #include <i2c/i2c.h> #include <rtc.h> @@ -31,7 +32,9 @@ */ enum ds_type { ds_1307, + ds_1337, ds_1338, + ds_1341, last_ds_type /* always last */ }; @@ -62,6 +65,28 @@ enum ds_type { # define DS1307_BIT_SQWE 0x10 # define DS1307_BIT_RS1 0x02 # define DS1307_BIT_RS0 0x01 +#define DS1337_REG_CONTROL 0x0e +# define DS1337_BIT_nEOSC 0x80 +# define DS1339_BIT_BBSQI 0x20 +# define DS3231_BIT_BBSQW 0x40 /* same as BBSQI */ +# define DS1337_BIT_RS2 0x10 +# define DS1337_BIT_RS1 0x08 +# define DS1337_BIT_INTCN 0x04 +# define DS1337_BIT_A2IE 0x02 +# define DS1337_BIT_A1IE 0x01 +#define DS1340_REG_CONTROL 0x07 +# define DS1340_BIT_OUT 0x80 +# define DS1340_BIT_FT 0x40 +# define DS1340_BIT_CALIB_SIGN 0x20 +# define DS1340_M_CALIBRATION 0x1f +#define DS1340_REG_FLAG 0x09 +# define DS1340_BIT_OSF 0x80 +#define DS1337_REG_STATUS 0x0f +# define DS1337_BIT_OSF 0x80 +# define DS1341_BIT_ECLK 0x04 +# define DS1337_BIT_A2I 0x02 +# define DS1337_BIT_A1I 0x01 + struct ds1307 { struct rtc_device rtc; @@ -78,7 +103,9 @@ struct ds1307 { static struct platform_device_id ds1307_id[] = { { "ds1307", ds_1307 }, + { "ds1337", ds_1337 }, { "ds1338", ds_1338 }, + { "ds1341", ds_1341 }, { "pt7c4338", ds_1307 }, { } }; @@ -224,6 +251,16 @@ static int ds1307_set_time(struct rtc_device *rtcdev, struct rtc_time *t) tmp = t->tm_year - 100; buf[DS1307_REG_YEAR] = bin2bcd(tmp); + switch (ds1307->type) { + case ds_1337: + case ds_1341: + buf[DS1307_REG_MONTH] |= DS1337_BIT_CENTURY; + break; + default: + break; + } + + dev_dbg(dev, "%s: %7ph\n", "write", buf); result = ds1307->write_block_data(ds1307->client, @@ -263,6 +300,61 @@ static int ds1307_probe(struct device_d *dev) ds1307->read_block_data = ds1307_read_block_data; ds1307->write_block_data = ds1307_write_block_data; + + switch (ds1307->type) { + case ds_1337: + case ds_1341: + /* get registers that the "rtc" read below won't read... */ + tmp = ds1307->read_block_data(ds1307->client, + DS1337_REG_CONTROL, 2, buf); + + if (tmp != 2) { + dev_dbg(&client->dev, "read error %d\n", tmp); + err = -EIO; + goto exit; + } + + /* oscillator off? turn it on, so clock can tick. */ + if (ds1307->regs[0] & DS1337_BIT_nEOSC) + ds1307->regs[0] &= ~DS1337_BIT_nEOSC; + + + /* + Make sure no alarm interrupts or square wave signals + are produced by the chip while we are in + bootloader. We do this by configuring the RTC to + generate alarm interrupts (thus disabling square + wave generation), but disabling each individual + alarm interrupt source + */ + ds1307->regs[0] |= DS1337_BIT_INTCN; + ds1307->regs[0] &= ~(DS1337_BIT_A2IE | DS1337_BIT_A1IE); + + i2c_smbus_write_byte_data(client, DS1337_REG_CONTROL, + ds1307->regs[0]); + + /* + For the above to be true, DS1341 also has to have + ECLK bit set to 0 + */ + if (ds1307->type == ds_1341) { + ds1307->regs[1] &= DS1341_BIT_ECLK; + i2c_smbus_write_byte_data(client, DS1337_REG_STATUS, + ds1307->regs[1]); + } + + + /* oscillator fault? clear flag, and warn */ + if (ds1307->regs[1] & DS1337_BIT_OSF) { + i2c_smbus_write_byte_data(client, DS1337_REG_STATUS, + ds1307->regs[1] & ~DS1337_BIT_OSF); + dev_warn(&client->dev, "SET TIME!\n"); + } + + default: + break; + } + read_rtc: /* read RTC registers */ tmp = ds1307->read_block_data(client, ds1307->offset, 8, buf); @@ -331,6 +423,8 @@ read_rtc: err = rtc_register(&ds1307->rtc); exit: + if (err) + free(ds1307); return err; } diff --git a/drivers/rtc/rtc-lib.c b/drivers/rtc/rtc-lib.c index 1b23458a57..83d80455da 100644 --- a/drivers/rtc/rtc-lib.c +++ b/drivers/rtc/rtc-lib.c @@ -90,6 +90,8 @@ int rtc_valid_tm(struct rtc_time *tm) { if (tm->tm_year < 70 || ((unsigned)tm->tm_mon) >= 12 + || tm->tm_wday < 0 + || tm->tm_wday > 6 || tm->tm_mday < 1 || tm->tm_mday > rtc_month_days(tm->tm_mon, tm->tm_year + 1900) || ((unsigned)tm->tm_hour) >= 24 diff --git a/drivers/usb/imx/chipidea-imx.c b/drivers/usb/imx/chipidea-imx.c index ae307183bc..a1c36cf644 100644 --- a/drivers/usb/imx/chipidea-imx.c +++ b/drivers/usb/imx/chipidea-imx.c @@ -242,7 +242,8 @@ static int imx_chipidea_probe(struct device_d *dev) ci->vbus = regulator_get(dev, "vbus"); - regulator_enable(ci->vbus); + if (!IS_ERR(ci->vbus)) + regulator_enable(ci->vbus); base = dev_request_mem_region(dev, 0); if (IS_ERR(base)) diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index eabd246d53..7ff67e525e 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -82,11 +82,11 @@ config DRIVER_VIDEO_PXA Add support for the frame buffer device found on the PXA270 CPU. -config DRIVER_VIDEO_BCM2835 - bool "BCM2835 framebuffer driver" - depends on ARCH_BCM2835 +config DRIVER_VIDEO_BCM283X + bool "BCM283X framebuffer driver" + depends on ARCH_BCM283X help - Add support for the BCM2835/VideoCore frame buffer device. + Add support for the BCM283X/VideoCore frame buffer device. source drivers/video/imx-ipu-v3/Kconfig diff --git a/drivers/video/Makefile b/drivers/video/Makefile index 57e4864a6d..a64fc5f24d 100644 --- a/drivers/video/Makefile +++ b/drivers/video/Makefile @@ -17,6 +17,6 @@ obj-$(CONFIG_DRIVER_VIDEO_S3C24XX) += s3c24xx.o obj-$(CONFIG_DRIVER_VIDEO_PXA) += pxa.o obj-$(CONFIG_DRIVER_VIDEO_SDL) += sdl.o obj-$(CONFIG_DRIVER_VIDEO_OMAP) += omap.o -obj-$(CONFIG_DRIVER_VIDEO_BCM2835) += bcm2835.o +obj-$(CONFIG_DRIVER_VIDEO_BCM283X) += bcm2835.o obj-$(CONFIG_DRIVER_VIDEO_SIMPLEFB) += simplefb.o obj-$(CONFIG_DRIVER_VIDEO_IMX_IPUV3) += imx-ipu-v3/ |