diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/ata/disk_ata_drive.c | 3 | ||||
-rw-r--r-- | drivers/ata/ide-sff.c | 54 | ||||
-rw-r--r-- | drivers/clk/clk-fixed-factor.c | 2 | ||||
-rw-r--r-- | drivers/clk/clk-fixed.c | 2 | ||||
-rw-r--r-- | drivers/clocksource/mvebu.c | 2 | ||||
-rw-r--r-- | drivers/net/phy/mdio-gpio.c | 2 | ||||
-rw-r--r-- | drivers/usb/gadget/Kconfig | 11 | ||||
-rw-r--r-- | drivers/usb/gadget/Makefile | 1 | ||||
-rw-r--r-- | drivers/usb/gadget/autostart.c | 70 | ||||
-rw-r--r-- | drivers/video/edid.c | 2 | ||||
-rw-r--r-- | drivers/watchdog/Kconfig | 6 | ||||
-rw-r--r-- | drivers/watchdog/Makefile | 1 | ||||
-rw-r--r-- | drivers/watchdog/orion_wdt.c | 123 |
13 files changed, 261 insertions, 18 deletions
diff --git a/drivers/ata/disk_ata_drive.c b/drivers/ata/disk_ata_drive.c index 1aa1bb1456..5ebddbdec8 100644 --- a/drivers/ata/disk_ata_drive.c +++ b/drivers/ata/disk_ata_drive.c @@ -237,6 +237,9 @@ static int ata_port_init(struct ata_port *port) #ifdef DEBUG ata_dump_id(port->id); #endif + + port->lba48 = ata_id_has_lba48(port->id); + if (port->devname) { port->blk.cdev.name = xstrdup(port->devname); } else { diff --git a/drivers/ata/ide-sff.c b/drivers/ata/ide-sff.c index 6dc89d79a5..b7c8847266 100644 --- a/drivers/ata/ide-sff.c +++ b/drivers/ata/ide-sff.c @@ -136,17 +136,33 @@ static int ata_wait_ready(struct ide_port *ide, unsigned timeout) * @param io Register file * @param drive 0 master drive, 1 slave drive * @param num Sector number - * - * @todo LBA48 support */ -static int ata_set_lba_sector(struct ide_port *ide, unsigned drive, uint64_t num) +static int ata_set_lba_sector(struct ata_port *port, unsigned drive, + uint64_t num) { - if (num > 0x0FFFFFFF || drive > 1) + struct ide_port *ide = to_ata_drive_access(port); + + if (drive > 1) return -EINVAL; - ata_wr_byte(ide, 0xA0 | LBA_FLAG | drive << 4 | num >> 24, - ide->io.device_addr); - ata_wr_byte(ide, 0x00, ide->io.error_addr); + if (port->lba48) { + if (num > (1ULL << 48) - 1) + return -EINVAL; + + ata_wr_byte(ide, LBA_FLAG | drive << 4, ide->io.device_addr); + + ata_wr_byte(ide, 0x00, ide->io.nsect_addr); + ata_wr_byte(ide, num >> 24, ide->io.lbal_addr); + ata_wr_byte(ide, num >> 32, ide->io.lbam_addr); + ata_wr_byte(ide, num >> 40, ide->io.lbah_addr); + } else { + if (num > (1ULL << 28) - 1) + return -EINVAL; + + ata_wr_byte(ide, 0xA0 | LBA_FLAG | drive << 4 | num >> 24, + ide->io.device_addr); + } + ata_wr_byte(ide, 0x01, ide->io.nsect_addr); ata_wr_byte(ide, num, ide->io.lbal_addr); /* 0 ... 7 */ ata_wr_byte(ide, num >> 8, ide->io.lbam_addr); /* 8 ... 15 */ @@ -316,10 +332,18 @@ static int ide_read(struct ata_port *port, void *buffer, unsigned int block, struct ide_port *ide = to_ata_drive_access(port); while (num_blocks) { - rc = ata_set_lba_sector(ide, DISK_MASTER, sector); + uint8_t cmd; + + rc = ata_set_lba_sector(port, DISK_MASTER, sector); if (rc != 0) return rc; - rc = ata_wr_cmd(ide, ATA_CMD_READ); + + if (port->lba48) + cmd = ATA_CMD_PIO_READ_EXT; + else + cmd = ATA_CMD_READ; + + rc = ata_wr_cmd(ide, cmd); if (rc != 0) return rc; rc = ata_wait_ready(ide, MAX_TIMEOUT); @@ -355,10 +379,18 @@ static int __maybe_unused ide_write(struct ata_port *port, struct ide_port *ide = to_ata_drive_access(port); while (num_blocks) { - rc = ata_set_lba_sector(ide, DISK_MASTER, sector); + uint8_t cmd; + + rc = ata_set_lba_sector(port, DISK_MASTER, sector); if (rc != 0) return rc; - rc = ata_wr_cmd(ide, ATA_CMD_WRITE); + + if (port->lba48) + cmd = ATA_CMD_PIO_WRITE_EXT; + else + cmd = ATA_CMD_WRITE; + + rc = ata_wr_cmd(ide, cmd); if (rc != 0) return rc; rc = ata_wait_ready(ide, MAX_TIMEOUT); diff --git a/drivers/clk/clk-fixed-factor.c b/drivers/clk/clk-fixed-factor.c index a3dbf334a8..0be48558e6 100644 --- a/drivers/clk/clk-fixed-factor.c +++ b/drivers/clk/clk-fixed-factor.c @@ -93,7 +93,6 @@ struct clk *clk_fixed_factor(const char *name, return &f->clk; } -#if defined(CONFIG_COMMON_CLK_OF_PROVIDER) /** * of_fixed_factor_clk_setup() - Setup function for simple fixed factor clock */ @@ -127,4 +126,3 @@ static int of_fixed_factor_clk_setup(struct device_node *node) } CLK_OF_DECLARE(fixed_factor_clk, "fixed-factor-clock", of_fixed_factor_clk_setup); -#endif diff --git a/drivers/clk/clk-fixed.c b/drivers/clk/clk-fixed.c index f0f7fbaed5..57bf36b39e 100644 --- a/drivers/clk/clk-fixed.c +++ b/drivers/clk/clk-fixed.c @@ -55,7 +55,6 @@ struct clk *clk_fixed(const char *name, int rate) return &fix->clk; } -#if defined(CONFIG_COMMON_CLK_OF_PROVIDER) /** * of_fixed_clk_setup() - Setup function for simple fixed rate clock */ @@ -76,4 +75,3 @@ static int of_fixed_clk_setup(struct device_node *node) return of_clk_add_provider(node, of_clk_src_simple_get, clk); } CLK_OF_DECLARE(fixed_clk, "fixed-clock", of_fixed_clk_setup); -#endif diff --git a/drivers/clocksource/mvebu.c b/drivers/clocksource/mvebu.c index cf80571263..59bbc4be22 100644 --- a/drivers/clocksource/mvebu.c +++ b/drivers/clocksource/mvebu.c @@ -60,7 +60,7 @@ static int mvebu_timer_probe(struct device_d *dev) struct clk *clk; u32 rate, div, val; - iores = dev_request_mem_resource(dev, 0); + iores = dev_get_resource(dev, IORESOURCE_MEM, 0); if (IS_ERR(iores)) return PTR_ERR(iores); timer_base = IOMEM(iores->start); diff --git a/drivers/net/phy/mdio-gpio.c b/drivers/net/phy/mdio-gpio.c index a839f2dee8..a846fb28e2 100644 --- a/drivers/net/phy/mdio-gpio.c +++ b/drivers/net/phy/mdio-gpio.c @@ -45,7 +45,7 @@ struct mdio_gpio_info { int mdc_active_low, mdio_active_low, mdo_active_low; }; -struct mdio_gpio_info *mdio_gpio_of_get_info(struct device_d *dev) +static struct mdio_gpio_info *mdio_gpio_of_get_info(struct device_d *dev) { int ret; enum of_gpio_flags flags; diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig index eb279ae8df..4292371f09 100644 --- a/drivers/usb/gadget/Kconfig +++ b/drivers/usb/gadget/Kconfig @@ -30,6 +30,17 @@ config USB_GADGET_DRIVER_PXA27X default y select USB_GADGET_DUALSPEED +config USB_GADGET_AUTOSTART + bool + default y + select ENVIRONMENT_VARIABLES + select FILE_LIST + prompt "Automatically start usbgadget on boot" + help + Enabling this option allows to automatically start a fastboot + gadget during boot. This behaviour is controlled with the + global.usbgadget.fastboot_function variable. + comment "USB Gadget drivers" config USB_GADGET_DFU diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile index 9ef594575b..e74cf02664 100644 --- a/drivers/usb/gadget/Makefile +++ b/drivers/usb/gadget/Makefile @@ -1,5 +1,6 @@ obj-$(CONFIG_USB_GADGET) += composite.o config.o usbstring.o epautoconf.o udc-core.o functions.o config.o multi.o +obj-$(CONFIG_USB_GADGET_AUTOSTART) += autostart.o obj-$(CONFIG_USB_GADGET_SERIAL) += u_serial.o serial.o f_serial.o f_acm.o obj-$(CONFIG_USB_GADGET_DFU) += dfu.o obj-$(CONFIG_USB_GADGET_FASTBOOT) += f_fastboot.o diff --git a/drivers/usb/gadget/autostart.c b/drivers/usb/gadget/autostart.c new file mode 100644 index 0000000000..4ad1dd6be1 --- /dev/null +++ b/drivers/usb/gadget/autostart.c @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2017 Oleksij Rempel <o.rempel@pengutronix.de>, Pengutronix + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ +#include <common.h> +#include <command.h> +#include <errno.h> +#include <environment.h> +#include <malloc.h> +#include <getopt.h> +#include <fs.h> +#include <xfuncs.h> +#include <usb/usbserial.h> +#include <usb/dfu.h> +#include <usb/gadget-multi.h> +#include <globalvar.h> +#include <magicvar.h> + +static int autostart; +static int acm; +static char *fastboot_function; + +static int usbgadget_autostart(void) +{ + struct f_multi_opts opts = {}; + + if (!autostart) + return 0; + + setenv("otg.mode", "peripheral"); + + if (fastboot_function) + opts.fastboot_opts.files = file_list_parse(fastboot_function); + + opts.create_acm = acm; + + return usb_multi_register(&opts); +} +postenvironment_initcall(usbgadget_autostart); + +static int usbgadget_globalvars_init(void) +{ + + globalvar_add_simple_bool("usbgadget.autostart", &autostart); + globalvar_add_simple_bool("usbgadget.acm", &acm); + globalvar_add_simple_string("usbgadget.fastboot_function", + &fastboot_function); + + return 0; +} +device_initcall(usbgadget_globalvars_init); + +BAREBOX_MAGICVAR_NAMED(global_usbgadget_autostart, + global.usbgadget.autostart, + "usbgadget: Automatically start usbgadget on boot"); +BAREBOX_MAGICVAR_NAMED(global_usbgadget_acm, + global.usbgadget.acm, + "usbgadget: Create CDC ACM function"); +BAREBOX_MAGICVAR_NAMED(global_usbgadget_fastboot_function, + global.usbgadget.fastboot_function, + "usbgadget: Create Android Fastboot function"); diff --git a/drivers/video/edid.c b/drivers/video/edid.c index 258526433e..bee4594118 100644 --- a/drivers/video/edid.c +++ b/drivers/video/edid.c @@ -387,7 +387,7 @@ static void fb_timings_vfreq(struct __fb_timings *timings) * REQUIRES: * A valid info->monspecs, otherwise 'safe numbers' will be used. */ -int fb_get_mode(int flags, u32 val, struct fb_videomode *var) +static int fb_get_mode(int flags, u32 val, struct fb_videomode *var) { struct __fb_timings *timings; u32 interlace = 1, dscan = 1; diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index 63fb1a8c57..83b6528a5f 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -46,4 +46,10 @@ config WATCHDOG_OMAP help Add support for watchdog on the TI OMAP SoC. +config WATCHDOG_ORION + bool "Watchdog for Armada XP" + depends on ARCH_ARMADA_XP + help + Add support for watchdog on the Marvall Armada XP + endif diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile index 5fca4c368c..a3b26675ce 100644 --- a/drivers/watchdog/Makefile +++ b/drivers/watchdog/Makefile @@ -5,3 +5,4 @@ obj-$(CONFIG_WATCHDOG_MXS28) += im28wd.o obj-$(CONFIG_WATCHDOG_DW) += dw_wdt.o obj-$(CONFIG_WATCHDOG_JZ4740) += jz4740.o obj-$(CONFIG_WATCHDOG_IMX_RESET_SOURCE) += imxwd.o +obj-$(CONFIG_WATCHDOG_ORION) += orion_wdt.o diff --git a/drivers/watchdog/orion_wdt.c b/drivers/watchdog/orion_wdt.c new file mode 100644 index 0000000000..2802033f71 --- /dev/null +++ b/drivers/watchdog/orion_wdt.c @@ -0,0 +1,123 @@ +/* + * Watchdog driver for Marvell Armada XP. + * + * Copyright (C) 2017 Pengutronix, Uwe Kleine-König <kernel@pengutronix.de> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <common.h> +#include <errno.h> +#include <init.h> +#include <io.h> +#include <malloc.h> +#include <of.h> +#include <watchdog.h> + +#define CLKRATE 25000000 + +/* registers relative to timer_base (i.e. first reg property) */ +#define TIMER_CTRL 0x00 +#define TIMER_CTRL_WD_TIMER_25MHZ_EN BIT(10) +#define TIMER_CTRL_WD_TIMER_EN BIT(8) + +#define TIMER_STATUS 0x04 +#define TIMER_STATUS_WD_EXPIRED BIT(31) + +#define TIMER_WD_TIMER 0x34 + +/* registers relative to rstout_base (i.e. second reg property) */ +#define WD_RSTOUTn_MASK 0x00 +#define WD_RSTOUTn_MASK_GLOBAL_WD BIT(8) + +struct orion_wdt_ddata { + struct watchdog wd; + void __iomem *timer_base; + void __iomem *rstout_base; +}; + +static int armada_xp_set_timeout(struct watchdog *wd, unsigned timeout) +{ + struct orion_wdt_ddata *ddata = + container_of(wd, struct orion_wdt_ddata, wd); + u32 ctrl; + + if (0xffffffff / CLKRATE < timeout) + return -EINVAL; + + ctrl = readl(ddata->timer_base + TIMER_CTRL); + + if (timeout == 0) { + /* disable timer */ + ctrl &= ~TIMER_CTRL_WD_TIMER_EN; + writel(ctrl, ddata->timer_base + TIMER_CTRL); + + return 0; + } + + /* setup duration */ + writel(CLKRATE * timeout, ddata->timer_base + TIMER_WD_TIMER); + + /* clear expiration status */ + writel(readl(ddata->timer_base + TIMER_STATUS) & ~TIMER_STATUS_WD_EXPIRED, + ddata->timer_base + TIMER_STATUS); + + /* assert reset on expiration */ + writel(WD_RSTOUTn_MASK_GLOBAL_WD, ddata->rstout_base + WD_RSTOUTn_MASK); + + /* enable */ + ctrl |= TIMER_CTRL_WD_TIMER_25MHZ_EN | TIMER_CTRL_WD_TIMER_EN; + writel(ctrl, ddata->timer_base + TIMER_CTRL); + + return 0; +} + +static int orion_wdt_probe(struct device_d *dev) +{ + struct orion_wdt_ddata* ddata; + struct resource *res_timer, *res_rstout; + + ddata = xzalloc(sizeof(*ddata)); + + ddata->wd.set_timeout = armada_xp_set_timeout; + ddata->wd.name = "orion_wdt"; + ddata->wd.dev = dev; + + res_timer = dev_request_mem_resource(dev, 0); + if (IS_ERR(res_timer)) { + dev_err(dev, "could not get timer memory region\n"); + return PTR_ERR(res_timer); + } + ddata->timer_base = IOMEM(res_timer->start); + + res_rstout = dev_request_mem_resource(dev, 1); + if (IS_ERR(res_rstout)) { + dev_err(dev, "could not get rstout memory region\n"); + release_region(res_timer); + + return PTR_ERR(res_rstout); + } + ddata->rstout_base = IOMEM(res_rstout->start); + + return watchdog_register(&ddata->wd); +} + +static const struct of_device_id orion_wdt_of_match[] = { + { + .compatible = "marvell,armada-xp-wdt", + }, { /* sentinel */ } +}; + +static struct driver_d orion_wdt_driver = { + .probe = orion_wdt_probe, + .name = "orion_wdt", + .of_compatible = DRV_OF_COMPAT(orion_wdt_of_match), +}; +device_platform_driver(orion_wdt_driver); |