diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/block/efi-block-io.c | 17 | ||||
-rw-r--r-- | drivers/efi/efi-device.c | 10 | ||||
-rw-r--r-- | drivers/hw_random/Kconfig | 6 | ||||
-rw-r--r-- | drivers/mfd/superio.c | 2 | ||||
-rw-r--r-- | drivers/net/designware.h | 1 | ||||
-rw-r--r-- | drivers/net/designware_socfpga.c | 133 | ||||
-rw-r--r-- | drivers/of/of_gpio.c | 6 | ||||
-rw-r--r-- | drivers/of/of_path.c | 2 | ||||
-rw-r--r-- | drivers/serial/efi-stdio.c | 78 | ||||
-rw-r--r-- | drivers/serial/efi-stdio.h | 58 | ||||
-rw-r--r-- | drivers/usb/storage/usb.c | 7 |
11 files changed, 277 insertions, 43 deletions
diff --git a/drivers/block/efi-block-io.c b/drivers/block/efi-block-io.c index d167d814c2..39dbfb0f7a 100644 --- a/drivers/block/efi-block-io.c +++ b/drivers/block/efi-block-io.c @@ -14,6 +14,7 @@ #include <disks.h> #include <efi/efi.h> #include <efi/efi-device.h> +#include <bootsource.h> #define EFI_BLOCK_IO_PROTOCOL_REVISION2 0x00020001 #define EFI_BLOCK_IO_PROTOCOL_REVISION3 ((2<<16) | (31)) @@ -145,6 +146,7 @@ static int is_bio_usbdev(struct efi_device *efidev) static int efi_bio_probe(struct efi_device *efidev) { int ret; + int instance; struct efi_bio_priv *priv; struct efi_block_io_media *media; @@ -159,10 +161,14 @@ static int efi_bio_probe(struct efi_device *efidev) efi_bio_print_info(priv); priv->dev = &efidev->dev; - if (is_bio_usbdev(efidev)) - priv->blk.cdev.name = xasprintf("usbdisk%d", cdev_find_free_index("usbdisk")); - else - priv->blk.cdev.name = xasprintf("disk%d", cdev_find_free_index("disk")); + if (is_bio_usbdev(efidev)) { + instance = cdev_find_free_index("usbdisk"); + priv->blk.cdev.name = xasprintf("usbdisk%d", instance); + } else { + instance = cdev_find_free_index("disk"); + priv->blk.cdev.name = xasprintf("disk%d", instance); + } + priv->blk.blockbits = ffs(media->block_size) - 1; priv->blk.num_blocks = media->last_block + 1; priv->blk.ops = &efi_bio_ops; @@ -174,6 +180,9 @@ static int efi_bio_probe(struct efi_device *efidev) if (ret) return ret; + if (efi_get_bootsource() == efidev) + bootsource_set_instance(instance); + parse_partition_table(&priv->blk); return 0; diff --git a/drivers/efi/efi-device.c b/drivers/efi/efi-device.c index 305d337aab..a1aac2dd31 100644 --- a/drivers/efi/efi-device.c +++ b/drivers/efi/efi-device.c @@ -311,7 +311,7 @@ static int efi_bus_match(struct device_d *dev, struct driver_d *drv) int i; for (i = 0; i < efidev->num_guids; i++) { - if (!memcmp(&efidrv->guid, &efidev->guids[i], sizeof(efi_guid_t))) { + if (!efi_guidcmp(efidrv->guid, efidev->guids[i])) { BS->handle_protocol(efidev->handle, &efidev->guids[i], &efidev->protocol); return 0; @@ -398,13 +398,19 @@ static int is_bio_usbdev(struct efi_device *efidev) return 0; } +static struct efi_device *bootdev; + +struct efi_device *efi_get_bootsource(void) +{ + return bootdev; +} + static void efi_set_bootsource(void) { enum bootsource src = BOOTSOURCE_UNKNOWN; int instance = BOOTSOURCE_INSTANCE_UNKNOWN; efi_handle_t *efi_parent; - struct efi_device *bootdev; if (!efi_loaded_image->parent_handle) goto out; diff --git a/drivers/hw_random/Kconfig b/drivers/hw_random/Kconfig index c57928204d..242a7ef278 100644 --- a/drivers/hw_random/Kconfig +++ b/drivers/hw_random/Kconfig @@ -15,11 +15,11 @@ config HWRNG_MXC_RNGC Generator hardware found on some Freescale i.MX processors. config HWRNG_DEV_RANDOM - tristate "Linux /dev/random and /dev/urandom RNG" + tristate "Linux /dev/urandom RNG" depends on SANDBOX default y help - This driver allows use of the host provided /dev/random - and /dev/urandom as barebox HWRNGs. + This driver allows use of the host provided /dev/urandom + as barebox HWRNGs. endif diff --git a/drivers/mfd/superio.c b/drivers/mfd/superio.c index 0f08d56cb3..12d74b40f6 100644 --- a/drivers/mfd/superio.c +++ b/drivers/mfd/superio.c @@ -88,7 +88,7 @@ void superio_chip_add(struct superio_chip *siochip) &superio_regmap_config); if (IS_ERR(regmap)) pr_warn("creating %s regmap failed: %s\n", - chipname, strerror(-PTR_ERR(regmap))); + chipname, strerrorp(regmap)); ret = regmap_register_cdev(regmap, chipname); if (ret) diff --git a/drivers/net/designware.h b/drivers/net/designware.h index 305f674bf0..0a6a6bf1a4 100644 --- a/drivers/net/designware.h +++ b/drivers/net/designware.h @@ -35,6 +35,7 @@ struct dw_eth_dev { struct dw_eth_drvdata { bool enh_desc; + void *priv; }; struct dw_eth_dev *dwc_drv_probe(struct device_d *dev); diff --git a/drivers/net/designware_socfpga.c b/drivers/net/designware_socfpga.c index 77157c2b51..ce3ac38ebe 100644 --- a/drivers/net/designware_socfpga.c +++ b/drivers/net/designware_socfpga.c @@ -14,11 +14,27 @@ #include <net.h> #include <of_net.h> #include <linux/reset.h> -#include <mach/cyclone5-system-manager.h> #include <mfd/syscon.h> #include "designware.h" -#define SYSMGR_EMACGRP_CTRL_PTP_REF_CLK_MASK 0x00000010 +#define SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_GMII_MII 0x0 +#define SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_RGMII 0x1 +#define SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_RMII 0x2 +#define SYSMGR_EMACGRP_CTRL_PHYSEL0_LSB 0 +#define SYSMGR_EMACGRP_CTRL_PHYSEL1_LSB 2 +#define SYSMGR_EMACGRP_CTRL_PHYSEL_MASK 0x00000003 +#define SYSMGR_EMACGRP_CTRL_PTP_REF_CLK_MASK 0x00000010 +#define SYSMGR_GEN10_EMACGRP_CTRL_PTP_REF_CLK_MASK 0x00000100 + +#define SYSMGR_FPGAGRP_MODULE 0x00000028 +#define SYSMGR_FPGAGRP_MODULE_EMAC 0x00000004 +#define SYSMGR_FPGAINTF_EMAC_REG 0x00000070 +#define SYSMGR_FPGAINTF_EMAC_BIT 0x1 + +struct socfpga_dwc_dev; +struct socfpga_dwmac_ops { + int (*set_phy_mode)(struct socfpga_dwc_dev *dwmac_priv); +}; struct socfpga_dwc_dev { struct dw_eth_dev *priv; @@ -26,27 +42,36 @@ struct socfpga_dwc_dev { u32 reg_shift; void __iomem *sys_mgr_base; bool f2h_ptp_ref_clk; + const struct socfpga_dwmac_ops *ops; }; -static int socfpga_dwc_set_phy_mode(struct socfpga_dwc_dev *dwc_dev) +static int socfpga_set_phy_mode_common(int phymode, u32 *val) { - struct dw_eth_dev *eth_dev = dwc_dev->priv; - int phymode = eth_dev->interface; - u32 reg_offset = dwc_dev->reg_offset; - u32 reg_shift = dwc_dev->reg_shift; - u32 ctrl, val; - switch (phymode) { case PHY_INTERFACE_MODE_RGMII: case PHY_INTERFACE_MODE_RGMII_ID: - val = SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_RGMII; + *val = SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_RGMII; break; case PHY_INTERFACE_MODE_MII: case PHY_INTERFACE_MODE_GMII: case PHY_INTERFACE_MODE_SGMII: - val = SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_GMII_MII; + *val = SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_GMII_MII; break; default: + return -EINVAL; + } + return 0; +}; + +static int socfpga_gen5_set_phy_mode(struct socfpga_dwc_dev *dwc_dev) +{ + struct dw_eth_dev *eth_dev = dwc_dev->priv; + int phymode = eth_dev->interface; + u32 reg_offset = dwc_dev->reg_offset; + u32 reg_shift = dwc_dev->reg_shift; + u32 ctrl, val; + + if (socfpga_set_phy_mode_common(phymode, &val)) { dev_err(ð_dev->netdev.dev, "bad phy mode %d\n", phymode); return -EINVAL; } @@ -85,6 +110,54 @@ static int socfpga_dwc_set_phy_mode(struct socfpga_dwc_dev *dwc_dev) return 0; } +static int socfpga_gen10_set_phy_mode(struct socfpga_dwc_dev *dwc_dev) +{ + struct dw_eth_dev *eth_dev = dwc_dev->priv; + int phymode = eth_dev->interface; + u32 reg_offset = dwc_dev->reg_offset; + u32 reg_shift = dwc_dev->reg_shift; + u32 ctrl, val; + + if (socfpga_set_phy_mode_common(phymode, &val)) { + dev_err(ð_dev->netdev.dev, "bad phy mode %d\n", phymode); + return -EINVAL; + } + + /* Assert reset to the enet controller before changing the phy mode */ + if (eth_dev->rst) + reset_control_assert(eth_dev->rst); + + ctrl = readl(dwc_dev->sys_mgr_base + reg_offset); + ctrl &= ~(SYSMGR_EMACGRP_CTRL_PHYSEL_MASK << reg_shift); + ctrl |= val << reg_shift; + + if (dwc_dev->f2h_ptp_ref_clk || + phymode == PHY_INTERFACE_MODE_MII || + phymode == PHY_INTERFACE_MODE_GMII || + phymode == PHY_INTERFACE_MODE_SGMII) { + u32 module; + + ctrl |= SYSMGR_GEN10_EMACGRP_CTRL_PTP_REF_CLK_MASK; + module = readl(dwc_dev->sys_mgr_base + SYSMGR_FPGAINTF_EMAC_REG); + module |= (SYSMGR_FPGAINTF_EMAC_BIT << reg_shift); + + writel(module, dwc_dev->sys_mgr_base + SYSMGR_FPGAINTF_EMAC_REG); + } else { + ctrl &= ~SYSMGR_GEN10_EMACGRP_CTRL_PTP_REF_CLK_MASK; + } + + writel(ctrl, dwc_dev->sys_mgr_base + reg_offset); + + /* Deassert reset for the phy configuration to be sampled by + * the enet controller, and operation to start in requested mode + */ + if (eth_dev->rst) + reset_control_deassert(eth_dev->rst); + + return 0; +} + + static int socfpga_dwc_probe_dt(struct device_d *dev, struct socfpga_dwc_dev *priv) { u32 reg_offset, reg_shift; @@ -120,11 +193,21 @@ static int socfpga_dwc_ether_probe(struct device_d *dev) { struct socfpga_dwc_dev *dwc_dev; struct dw_eth_dev *priv; + struct dw_eth_drvdata *drvdata; int ret; dwc_dev = xzalloc(sizeof(*dwc_dev)); - priv = dwc_drv_probe(dev); + ret = dev_get_drvdata(dev, (const void **)&drvdata); + if (ret) + return ret; + + if (drvdata && drvdata->priv) + dwc_dev->ops = (struct socfpga_dwmac_ops *)drvdata->priv; + else + return -EINVAL; + + priv = dwc_drv_probe(dev); if (IS_ERR(priv)) return PTR_ERR(priv); @@ -145,18 +228,36 @@ static int socfpga_dwc_ether_probe(struct device_d *dev) if (ret) return ret; - return socfpga_dwc_set_phy_mode(dwc_dev); + return dwc_dev->ops->set_phy_mode(dwc_dev); } -static struct dw_eth_drvdata socfpga_stmmac_drvdata = { +static struct socfpga_dwmac_ops socfpga_gen5_ops = { + .set_phy_mode = socfpga_gen5_set_phy_mode, +}; + +static const struct dw_eth_drvdata socfpga_gen5_drvdata = { .enh_desc = 1, + .priv = &socfpga_gen5_ops, +}; + +static struct socfpga_dwmac_ops socfpga_gen10_ops = { + .set_phy_mode = socfpga_gen10_set_phy_mode, +}; +static const struct dw_eth_drvdata socfpga_gen10_drvdata = { + .enh_desc = 1, + .priv = &socfpga_gen10_ops, }; static __maybe_unused struct of_device_id socfpga_dwc_ether_compatible[] = { { .compatible = "altr,socfpga-stmmac", - .data = &socfpga_stmmac_drvdata, - }, { + .data = &socfpga_gen5_drvdata, + }, + { + .compatible = "altr,socfpga-stmmac-a10-s10", + .data = &socfpga_gen10_drvdata, + }, + { /* sentinel */ } }; diff --git a/drivers/of/of_gpio.c b/drivers/of/of_gpio.c index 9a8331ed18..7cbeeaf69e 100644 --- a/drivers/of/of_gpio.c +++ b/drivers/of/of_gpio.c @@ -19,18 +19,20 @@ static void of_gpio_flags_quirks(struct device_node *np, (!(strcmp(propname, "enable-gpio") && strcmp(propname, "enable-gpios")) && of_device_is_compatible(np, "regulator-gpio")))) { + bool active_low = !of_property_read_bool(np, + "enable-active-high"); /* * The regulator GPIO handles are specified such that the * presence or absence of "enable-active-high" solely controls * the polarity of the GPIO line. Any phandle flags must * be actively ignored. */ - if (*flags & OF_GPIO_ACTIVE_LOW) { + if ((*flags & OF_GPIO_ACTIVE_LOW) && !active_low) { pr_warn("%s GPIO handle specifies active low - ignored\n", np->full_name); *flags &= ~OF_GPIO_ACTIVE_LOW; } - if (!of_property_read_bool(np, "enable-active-high")) + if (active_low) *flags |= OF_GPIO_ACTIVE_LOW; } } diff --git a/drivers/of/of_path.c b/drivers/of/of_path.c index f8bbf2cba1..5c3a020345 100644 --- a/drivers/of/of_path.c +++ b/drivers/of/of_path.c @@ -83,7 +83,7 @@ static int __of_find_path(struct device_node *node, const char *part, char **out } if (dev->bus && !dev->driver) - return -ENODEV; + return -EPROBE_DEFER; device_detect(dev); diff --git a/drivers/serial/efi-stdio.c b/drivers/serial/efi-stdio.c index 2ca89fa4f8..9e825181e6 100644 --- a/drivers/serial/efi-stdio.c +++ b/drivers/serial/efi-stdio.c @@ -26,6 +26,8 @@ #include <readkey.h> #include <linux/ctype.h> #include <efi/efi.h> +#include <efi/efi-device.h> +#include "efi-stdio.h" #define EFI_SHIFT_STATE_VALID 0x80000000 #define EFI_RIGHT_CONTROL_PRESSED 0x00000004 @@ -71,6 +73,7 @@ struct efi_console_priv { struct efi_simple_text_output_protocol *out; struct efi_simple_input_interface *in; + struct efi_simple_text_input_ex_protocol *inex; struct console_device cdev; int lastkey; u16 efi_console_buffer[CONFIG_CBSIZE]; @@ -105,35 +108,72 @@ static struct efi_ctrlkey ctrlkeys[] = { { 0x17, 27 /* escape key */ }, }; +static int xlate_keypress(struct efi_input_key *k) +{ + int i; + + /* 32 bit modifier keys + 16 bit scan code + 16 bit unicode */ + for (i = 0; i < ARRAY_SIZE(ctrlkeys); i++) { + if (ctrlkeys[i].scan_code == k->scan_code) + return ctrlkeys[i].bb_key; + + } + + return k->unicode_char & 0xff; +} + static int efi_read_key(struct efi_console_priv *priv, bool wait) { unsigned long index; efi_status_t efiret; - struct efi_input_key k; - int i; + struct efi_key_data kd; /* wait until key is pressed */ if (wait) BS->wait_for_event(1, priv->in->wait_for_key, &index); - efiret = priv->in->read_key_stroke(efi_sys_table->con_in, &k); - if (EFI_ERROR(efiret)) - return -efi_errno(efiret); + if (priv->inex) { + efiret = priv->inex->read_key_stroke_ex(priv->inex, &kd); - /* 32 bit modifier keys + 16 bit scan code + 16 bit unicode */ - for (i = 0; i < ARRAY_SIZE(ctrlkeys); i++) { - if (ctrlkeys[i].scan_code == k.scan_code) - return ctrlkeys[i].bb_key; + if (efiret == EFI_NOT_READY) + return -EAGAIN; + + if (!EFI_ERROR(efiret)) { + if ((kd.state.shift_state & EFI_SHIFT_STATE_VALID) && + (kd.state.shift_state & EFI_CONTROL_PRESSED)) { + int ch = tolower(kd.key.unicode_char & 0xff); + + if (isalpha(ch)) + return CHAR_CTRL(ch); + if (ch == '\0') /* ctrl is pressed on its own */ + return -EAGAIN; + } + + if (kd.key.unicode_char || kd.key.scan_code) + return xlate_keypress(&kd.key); + /* Some broken firmwares offer simple_text_input_ex_protocol, + * but never handle any key. Treat those as if + * read_key_stroke_ex failed and fall through + * to the basic simple_text_input_protocol. + */ + dev_dbg(priv->cdev.dev, "Falling back to simple_text_input_protocol\n"); + } } - return k.unicode_char & 0xff; + efiret = priv->in->read_key_stroke(priv->in, &kd.key); + + if (EFI_ERROR(efiret)) + return -efi_errno(efiret); + + return xlate_keypress(&kd.key); } static void efi_console_putc(struct console_device *cdev, char c) { uint16_t str[2] = {}; - struct efi_simple_text_output_protocol *con_out = efi_sys_table->con_out; + struct efi_console_priv *priv = to_efi(cdev); + struct efi_simple_text_output_protocol *con_out = priv->out; str[0] = c; @@ -331,8 +371,12 @@ static void efi_set_mode(struct efi_console_priv *priv) static int efi_console_probe(struct device_d *dev) { + efi_guid_t inex_guid = EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL_GUID; + struct efi_simple_text_input_ex_protocol *inex; struct console_device *cdev; struct efi_console_priv *priv; + efi_status_t efiret; + int i; priv = xzalloc(sizeof(*priv)); @@ -340,6 +384,18 @@ static int efi_console_probe(struct device_d *dev) priv->out = efi_sys_table->con_out; priv->in = efi_sys_table->con_in; + efiret = BS->open_protocol((void *)efi_sys_table->con_in_handle, + &inex_guid, + (void **)&inex, + efi_parent_image, + 0, + EFI_OPEN_PROTOCOL_GET_PROTOCOL); + + if (!EFI_ERROR(efiret)) { + priv->inex = inex; + dev_dbg(dev, "Using simple_text_input_ex_protocol\n"); + } + priv->current_color = EFI_WHITE; efi_set_mode(priv); diff --git a/drivers/serial/efi-stdio.h b/drivers/serial/efi-stdio.h new file mode 100644 index 0000000000..1fa417c706 --- /dev/null +++ b/drivers/serial/efi-stdio.h @@ -0,0 +1,58 @@ +#ifndef EFI_STDIO_H_ +#define EFI_STDIO_H_ + +#include <efi.h> + +struct efi_simple_text_input_ex_protocol; + +typedef efi_status_t (EFIAPI *efi_input_reset_ex)( + struct efi_simple_text_input_ex_protocol *this, + efi_bool_t extended_verification +); + +struct efi_key_state { + u32 shift_state; + u8 toggle_state; +}; + +struct efi_key_data { + struct efi_input_key key; + struct efi_key_state state; +}; + +typedef efi_status_t (EFIAPI *efi_input_read_key_ex)( + struct efi_simple_text_input_ex_protocol *this, + struct efi_key_data *keydata +); + +typedef efi_status_t (EFIAPI *efi_set_state)( + struct efi_simple_text_input_ex_protocol *this, + u8 *key_toggle_state +); + +typedef efi_status_t (EFIAPI *efi_key_notify_function)( + struct efi_key_data *keydata +); + +typedef efi_status_t (EFIAPI *efi_register_keystroke_notify)( + struct efi_simple_text_input_ex_protocol *this, + struct efi_key_data keydata, + efi_key_notify_function key_notification_function, + void **notify_handle +); + +typedef efi_status_t (EFIAPI *efi_unregister_keystroke_notify)( + struct efi_simple_text_input_ex_protocol *this, + void *notification_handle +); + +struct efi_simple_text_input_ex_protocol { + efi_input_reset_ex reset; + efi_input_read_key_ex read_key_stroke_ex; + void *wait_for_key_ex; + efi_set_state set_state; + efi_register_keystroke_notify register_key_notify; + efi_unregister_keystroke_notify unregister_key_notify; +}; + +#endif diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c index 63d624e91b..e0ef4f5ef3 100644 --- a/drivers/usb/storage/usb.c +++ b/drivers/usb/storage/usb.c @@ -87,8 +87,7 @@ static int usb_stor_transport(struct us_blk_dev *usb_blkdev, struct device_d *dev = &us->pusb_dev->dev; int i, ret; - - for (i = 0; i < retries; i++) { + for (i = 0; i <= retries; i++) { dev_dbg(dev, "%s\n", usb_stor_opcode_name(cmd[0])); ret = us->transport(usb_blkdev, cmd, cmdlen, data, datalen); dev_dbg(dev, "%s returns %d\n", usb_stor_opcode_name(cmd[0]), @@ -105,6 +104,8 @@ static int usb_stor_transport(struct us_blk_dev *usb_blkdev, mdelay(request_sense_delay_ms); } + dev_dbg(dev, "Retried %s %d times, and failed.\n", usb_stor_opcode_name(cmd[0]), retries); + return -EIO; } @@ -194,7 +195,7 @@ static int usb_stor_io_10(struct us_blk_dev *usb_blkdev, u8 opcode, put_unaligned_be16(blocks, &cmd[7]); return usb_stor_transport(usb_blkdev, cmd, sizeof(cmd), data, - blocks * SECTOR_SIZE, 2, 0); + blocks * SECTOR_SIZE, 10, 0); } /*********************************************************************** |