diff options
author | Sascha Hauer <s.hauer@pengutronix.de> | 2020-03-18 08:48:17 +0100 |
---|---|---|
committer | Sascha Hauer <s.hauer@pengutronix.de> | 2020-03-18 08:48:17 +0100 |
commit | 8c02f14d1db16068a005b9674da42f14f344ab89 (patch) | |
tree | b57b9d55789ab59e63436ff70f569db06c228f50 /drivers | |
parent | 52ef5245746cb13d1eaf9d520d9e7a36d2a70d4b (diff) | |
parent | 544bd2f460da25de41094aceadb799ca31474d97 (diff) | |
download | barebox-8c02f14d1db16068a005b9674da42f14f344ab89.tar.gz barebox-8c02f14d1db16068a005b9674da42f14f344ab89.tar.xz |
Merge branch 'for-next/misc'
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/net/designware_eqos.c | 33 | ||||
-rw-r--r-- | drivers/net/designware_eqos.h | 1 | ||||
-rw-r--r-- | drivers/net/designware_stm32.c | 1 | ||||
-rw-r--r-- | drivers/net/designware_tegra186.c | 1 | ||||
-rw-r--r-- | drivers/of/overlay.c | 20 | ||||
-rw-r--r-- | drivers/usb/gadget/Kconfig | 11 | ||||
-rw-r--r-- | drivers/usb/gadget/f_fastboot.c | 4 | ||||
-rw-r--r-- | drivers/usb/host/ehci-hcd.c | 101 | ||||
-rw-r--r-- | drivers/video/ssd1307fb.c | 63 |
9 files changed, 131 insertions, 104 deletions
diff --git a/drivers/net/designware_eqos.c b/drivers/net/designware_eqos.c index 4ae07fe059..cb52f3942d 100644 --- a/drivers/net/designware_eqos.c +++ b/drivers/net/designware_eqos.c @@ -199,7 +199,7 @@ static int eqos_mdio_wait_idle(struct eqos *eqos) static int eqos_mdio_read(struct mii_bus *bus, int addr, int reg) { struct eqos *eqos = bus->priv; - u32 miiaddr; + u32 miiaddr = MII_BUSY; int ret; ret = eqos_mdio_wait_idle(eqos); @@ -208,18 +208,13 @@ static int eqos_mdio_read(struct mii_bus *bus, int addr, int reg) return ret; } - miiaddr = readl(&eqos->mac_regs->mdio_address); - miiaddr &= EQOS_MDIO_ADDR_SKAP | EQOS_MDIO_ADDR_C45E; - miiaddr |= EQOS_MDIO_ADDR_GOC_READ << EQOS_MDIO_ADDR_GOC_SHIFT; - - miiaddr |= EQOS_MDIO_CLK_CSR(eqos->ops->clk_csr); miiaddr |= EQOS_MDIO_ADDR(addr) | EQOS_MDIO_REG(reg); - miiaddr |= MII_BUSY; + miiaddr |= EQOS_MDIO_CLK_CSR(eqos->ops->clk_csr); + miiaddr |= EQOS_MDIO_ADDR_GOC_READ << EQOS_MDIO_ADDR_GOC_SHIFT; + writel(0, &eqos->mac_regs->mdio_data); writel(miiaddr, &eqos->mac_regs->mdio_address); - udelay(eqos->ops->mdio_wait_us); - ret = eqos_mdio_wait_idle(eqos); if (ret) { dev_err(&bus->dev, "MDIO read didn't complete\n"); @@ -232,7 +227,7 @@ static int eqos_mdio_read(struct mii_bus *bus, int addr, int reg) static int eqos_mdio_write(struct mii_bus *bus, int addr, int reg, u16 data) { struct eqos *eqos = bus->priv; - u32 miiaddr = 0; + u32 miiaddr = MII_BUSY; int ret; ret = eqos_mdio_wait_idle(eqos); @@ -241,28 +236,18 @@ static int eqos_mdio_write(struct mii_bus *bus, int addr, int reg, u16 data) return ret; } - miiaddr = readl(&eqos->mac_regs->mdio_address); - miiaddr &= EQOS_MDIO_ADDR_SKAP | EQOS_MDIO_ADDR_C45E; - miiaddr |= EQOS_MDIO_ADDR_GOC_WRITE << EQOS_MDIO_ADDR_GOC_SHIFT; - - miiaddr |= EQOS_MDIO_CLK_CSR(eqos->ops->clk_csr); miiaddr |= EQOS_MDIO_ADDR(addr) | EQOS_MDIO_REG(reg); - miiaddr |= MII_BUSY; + miiaddr |= EQOS_MDIO_CLK_CSR(eqos->ops->clk_csr); + miiaddr |= EQOS_MDIO_ADDR_GOC_WRITE << EQOS_MDIO_ADDR_GOC_SHIFT; writel(data, &eqos->mac_regs->mdio_data); writel(miiaddr, &eqos->mac_regs->mdio_address); - udelay(eqos->ops->mdio_wait_us); - ret = eqos_mdio_wait_idle(eqos); - if (ret) { + if (ret) dev_err(&bus->dev, "MDIO read didn't complete\n"); - return ret; - } - /* Needed as a fix for ST-Phy */ - eqos_mdio_read(bus, addr, reg); - return 0; + return ret; } diff --git a/drivers/net/designware_eqos.h b/drivers/net/designware_eqos.h index f794195db4..30f4f02579 100644 --- a/drivers/net/designware_eqos.h +++ b/drivers/net/designware_eqos.h @@ -17,7 +17,6 @@ struct eqos_ops { unsigned long (*get_csr_clk_rate)(struct eqos *); bool enh_desc; - int mdio_wait_us; #define EQOS_MAC_RXQ_CTRL0_RXQ0EN_SHIFT 0 #define EQOS_MAC_RXQ_CTRL0_RXQ0EN_MASK 3 diff --git a/drivers/net/designware_stm32.c b/drivers/net/designware_stm32.c index 1e0cdfa695..2e2af8942d 100644 --- a/drivers/net/designware_stm32.c +++ b/drivers/net/designware_stm32.c @@ -180,7 +180,6 @@ static struct eqos_ops stm32_ops = { .adjust_link = eqos_adjust_link, .get_csr_clk_rate = eqos_get_csr_clk_rate_stm32, - .mdio_wait_us = 10 * USEC_PER_MSEC, .clk_csr = EQOS_MDIO_ADDR_CR_250_300, .config_mac = EQOS_MAC_RXQ_CTRL0_RXQ0EN_ENABLED_AV, }; diff --git a/drivers/net/designware_tegra186.c b/drivers/net/designware_tegra186.c index 20521db1c7..5348f65c41 100644 --- a/drivers/net/designware_tegra186.c +++ b/drivers/net/designware_tegra186.c @@ -280,7 +280,6 @@ static const struct eqos_ops tegra186_ops = { .adjust_link = eqos_adjust_link_tegra186, .get_csr_clk_rate = eqos_get_csr_clk_rate_tegra186, - .mdio_wait_us = 10, .clk_csr = EQOS_MDIO_ADDR_CR_20_35, .config_mac = EQOS_MAC_RXQ_CTRL0_RXQ0EN_ENABLED_DCB, }; diff --git a/drivers/of/overlay.c b/drivers/of/overlay.c index de79e05cbc..a35eddfa08 100644 --- a/drivers/of/overlay.c +++ b/drivers/of/overlay.c @@ -105,7 +105,7 @@ static char *of_overlay_fix_path(struct device_node *root, return basprintf("%s%s", target->full_name, path_tail); } -static int of_overlay_apply_symbols(struct device_node *root, +static void of_overlay_apply_symbols(struct device_node *root, struct device_node *overlay) { const char *old_path; @@ -115,12 +115,12 @@ static int of_overlay_apply_symbols(struct device_node *root, struct device_node *overlay_symbols; root_symbols = of_get_child_by_name(root, "__symbols__"); - if (!root_symbols) - return -EINVAL; - overlay_symbols = of_get_child_by_name(overlay, "__symbols__"); - if (!overlay_symbols) - return -EINVAL; + + if (!overlay_symbols || !root_symbols) { + pr_info("overlay/root doesn't have a __symbols__ node\n"); + return; + } list_for_each_entry(prop, &overlay_symbols->properties, list) { if (of_prop_cmp(prop->name, "name") == 0) @@ -133,8 +133,6 @@ static int of_overlay_apply_symbols(struct device_node *root, prop->name, new_path); of_property_write_string(root_symbols, prop->name, new_path); } - - return 0; } static int of_overlay_apply_fragment(struct device_node *root, @@ -171,15 +169,13 @@ int of_overlay_apply_tree(struct device_node *root, return -EINVAL; /* Copy symbols from resolved overlay to base device tree */ - err = of_overlay_apply_symbols(root, resolved); - if (err) - pr_warn("failed to copy symbols from overlay"); + of_overlay_apply_symbols(root, resolved); /* Copy nodes and properties from resolved overlay to root */ for_each_child_of_node(resolved, fragment) { err = of_overlay_apply_fragment(root, fragment); if (err) - pr_warn("failed to apply %s", fragment->name); + pr_warn("failed to apply %s\n", fragment->name); } of_delete_node(resolved); diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig index 3c1d7e6f18..6e60c7aee8 100644 --- a/drivers/usb/gadget/Kconfig +++ b/drivers/usb/gadget/Kconfig @@ -61,6 +61,7 @@ config USB_GADGET_FASTBOOT config USB_GADGET_FASTBOOT_SPARSE bool + depends on USB_GADGET_FASTBOOT select IMAGE_SPARSE prompt "Enable Fastboot sparse image support" help @@ -80,4 +81,14 @@ config USB_GADGET_FASTBOOT_BUF a buffer, then using a buffer might be better. Say no here unless you know what you are doing. + +config USB_GADGET_FASTBOOT_CMD_OEM + bool + depends on USB_GADGET_FASTBOOT + prompt "Enable OEM commands" + help + This option enables the fastboot "oem" group of commands. They allow to + executing arbitrary barebox commands and may be disabled in secure + environments. + endif diff --git a/drivers/usb/gadget/f_fastboot.c b/drivers/usb/gadget/f_fastboot.c index 426ee9db0b..cf3cc6dac7 100644 --- a/drivers/usb/gadget/f_fastboot.c +++ b/drivers/usb/gadget/f_fastboot.c @@ -1253,7 +1253,7 @@ static const struct cmd_dispatch_info cmd_oem_dispatch_info[] = { }, }; -static void cb_oem(struct f_fastboot *f_fb, const char *cmd) +static void __maybe_unused cb_oem(struct f_fastboot *f_fb, const char *cmd) { pr_debug("%s: \"%s\"\n", __func__, cmd); @@ -1281,9 +1281,11 @@ static const struct cmd_dispatch_info cmd_dispatch_info[] = { }, { .cmd = "erase:", .cb = cb_erase, +#if defined(CONFIG_USB_GADGET_FASTBOOT_CMD_OEM) }, { .cmd = "oem ", .cb = cb_oem, +#endif }, }; diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index 417ae5df75..ead63b2c9f 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -42,7 +42,9 @@ struct ehci_host { struct ehci_hcor *hcor; struct usb_host host; struct QH *qh_list; + dma_addr_t qh_list_dma; struct qTD *td; + dma_addr_t td_dma; int portreset; unsigned long flags; @@ -51,7 +53,9 @@ struct ehci_host { void *drvdata; int periodic_schedules; struct QH *periodic_queue; + dma_addr_t periodic_queue_dma; uint32_t *periodic_list; + dma_addr_t periodic_list_dma; }; struct int_queue { @@ -59,9 +63,11 @@ struct int_queue { int queuesize; unsigned long pipe; struct QH *first; + dma_addr_t first_dma; struct QH *current; struct QH *last; struct qTD *tds; + dma_addr_t tds_dma; }; #define to_ehci(ptr) container_of(ptr, struct ehci_host, host) @@ -137,6 +143,29 @@ static struct descriptor { #define ehci_is_TDI() (ehci->flags & EHCI_HAS_TT) +#define EHCI_DMA(dma0, ptr0, ptr) \ + ((dma0) + ((ptr) - (ptr0)) * sizeof(*(ptr))) + +static inline uint32_t ehci_qh_dma(struct ehci_host *ehci, struct QH *qh) +{ + return EHCI_DMA(ehci->qh_list_dma, ehci->qh_list, qh); +} + +static inline uint32_t ehci_td_dma(struct ehci_host *ehci, struct qTD *td) +{ + return EHCI_DMA(ehci->td_dma, ehci->td, td); +} + +static inline uint32_t ehci_int_qh_dma(struct int_queue *intq, struct QH *qh) +{ + return EHCI_DMA(intq->first_dma, intq->first, qh); +} + +static inline uint32_t ehci_int_td_dma(struct int_queue *intq, struct qTD *td) +{ + return EHCI_DMA(intq->tds_dma, intq->tds, td); +} + static void memzero32(void *ptr, size_t size) { uint32_t *ptr32 = ptr; @@ -346,7 +375,7 @@ ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer, dev_dbg(ehci->dev, "unable construct SETUP td\n"); return ret; } - *tdp = cpu_to_hc32((uint32_t) td); + *tdp = cpu_to_hc32(ehci_td_dma(ehci, td)); tdp = &td->qt_next; toggle = 1; @@ -385,7 +414,7 @@ ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer, dev_err(ehci->dev, "unable construct DATA td\n"); return ret; } - *tdp = cpu_to_hc32((uint32_t) td); + *tdp = cpu_to_hc32(ehci_td_dma(ehci, td)); tdp = &td->qt_next; } @@ -399,7 +428,7 @@ ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer, QT_TOKEN_PID_IN), NULL, 0, NULL, DMA_NONE); - *tdp = cpu_to_hc32((uint32_t)td); + *tdp = cpu_to_hc32(ehci_td_dma(ehci, td)); tdp = &td->qt_next; } @@ -841,7 +870,7 @@ static int ehci_init(struct usb_host *host) return ret; } - ehci->qh_list[0].qh_link = cpu_to_hc32((uint32_t)&ehci->qh_list[1] | + ehci->qh_list[0].qh_link = cpu_to_hc32(ehci_qh_dma(ehci, &ehci->qh_list[1]) | QH_LINK_TYPE_QH); ehci->qh_list[0].qh_endpt1 = cpu_to_hc32(QH_ENDPT1_H(1) | QH_ENDPT1_EPS(USB_SPEED_HIGH)); @@ -850,12 +879,13 @@ static int ehci_init(struct usb_host *host) ehci->qh_list[0].qt_altnext = cpu_to_hc32(QT_NEXT_TERMINATE); ehci->qh_list[0].qt_token = cpu_to_hc32(QT_TOKEN_STATUS_HALTED); - ehci->qh_list[1].qh_link = cpu_to_hc32((uint32_t)&ehci->qh_list[0] | + ehci->qh_list[1].qh_link = cpu_to_hc32(ehci_qh_dma(ehci, + &ehci->qh_list[0]) | QH_LINK_TYPE_QH); ehci->qh_list[1].qt_altnext = cpu_to_hc32(QT_NEXT_TERMINATE); /* Set async. queue head pointer. */ - ehci_writel(&ehci->hcor->or_asynclistaddr, (uint32_t)ehci->qh_list); + ehci_writel(&ehci->hcor->or_asynclistaddr, (uint32_t)ehci->qh_list_dma); /* * Set up periodic list @@ -885,15 +915,15 @@ static int ehci_init(struct usb_host *host) * PAGE_SIZE less then 4k will break this code. */ ehci->periodic_list = dma_alloc_coherent(1024 * 4, - DMA_ADDRESS_BROKEN); + &ehci->periodic_list_dma); for (i = 0; i < 1024; i++) { - ehci->periodic_list[i] = cpu_to_hc32((unsigned long)periodic + ehci->periodic_list[i] = cpu_to_hc32((unsigned long)ehci->periodic_queue_dma | QH_LINK_TYPE_QH); } /* Set periodic list base address */ ehci_writel(&ehci->hcor->or_periodiclistbase, - (unsigned long)ehci->periodic_list); + (uint32_t)ehci->periodic_list_dma); reg = ehci_readl(&ehci->hccr->cr_hcsparams); descriptor.hub.bNbrPorts = HCS_N_PORTS(reg); @@ -986,7 +1016,10 @@ disable_periodic(struct ehci_host *ehci) return 0; } -#define NEXT_QH(qh) (struct QH *)((unsigned long)hc32_to_cpu((qh)->qh_link) & ~0x1f) +#define NEXT_QH(queue, qh) (struct QH *)( \ + ((unsigned long)hc32_to_cpu((qh)->qh_link) & ~0x1f) - \ + (queue)->first_dma + \ + (unsigned long)(queue)->first) static int enable_periodic(struct ehci_host *ehci) @@ -1051,7 +1084,7 @@ static void ehci_update_endpt2_dev_n_port(struct usb_device *udev, static struct int_queue *ehci_create_int_queue(struct usb_device *dev, unsigned long pipe, int queuesize, int elementsize, - void *buffer, int interval) + void *buffer, dma_addr_t buffer_dma, int interval) { struct usb_host *host = dev->host; struct ehci_host *ehci = to_ehci(host); @@ -1100,22 +1133,23 @@ static struct int_queue *ehci_create_int_queue(struct usb_device *dev, result->queuesize = queuesize; result->pipe = pipe; result->first = dma_alloc_coherent(sizeof(struct QH) * queuesize, - DMA_ADDRESS_BROKEN); + &result->first_dma); result->current = result->first; result->last = result->first + queuesize - 1; result->tds = dma_alloc_coherent(sizeof(struct qTD) * queuesize, - DMA_ADDRESS_BROKEN); + &result->tds_dma); for (i = 0; i < queuesize; i++) { struct QH *qh = result->first + i; struct qTD *td = result->tds + i; void **buf = &qh->buffer; - qh->qh_link = cpu_to_hc32((unsigned long)(qh+1) | QH_LINK_TYPE_QH); + qh->qh_link = cpu_to_hc32(ehci_int_qh_dma(result, qh + 1) | + QH_LINK_TYPE_QH); if (i == queuesize - 1) qh->qh_link = cpu_to_hc32(QH_LINK_TERMINATE); - qh->qt_next = cpu_to_hc32((unsigned long)td); + qh->qt_next = cpu_to_hc32(ehci_int_td_dma(result, td)); qh->qt_altnext = cpu_to_hc32(QT_NEXT_TERMINATE); qh->qh_endpt1 = cpu_to_hc32((0 << 28) | /* No NAK reload (ehci 4.9) */ @@ -1142,15 +1176,15 @@ static struct int_queue *ehci_create_int_queue(struct usb_device *dev, ((usb_pipein(pipe) ? 1 : 0) << 8) | /* IN/OUT token */ 0x80); /* active */ td->qt_buffer[0] = - cpu_to_hc32((unsigned long)buffer + i * elementsize); + cpu_to_hc32(buffer_dma + i * elementsize); td->qt_buffer[1] = - cpu_to_hc32((td->qt_buffer[0] + 0x1000) & ~0xfff); + cpu_to_hc32((buffer_dma + i * elementsize + 0x1000) & ~0xfff); td->qt_buffer[2] = - cpu_to_hc32((td->qt_buffer[0] + 0x2000) & ~0xfff); + cpu_to_hc32((buffer_dma + i * elementsize + 0x2000) & ~0xfff); td->qt_buffer[3] = - cpu_to_hc32((td->qt_buffer[0] + 0x3000) & ~0xfff); + cpu_to_hc32((buffer_dma + i * elementsize + 0x3000) & ~0xfff); td->qt_buffer[4] = - cpu_to_hc32((td->qt_buffer[0] + 0x4000) & ~0xfff); + cpu_to_hc32((buffer_dma + i * elementsize + 0x4000) & ~0xfff); *buf = buffer + i * elementsize; } @@ -1165,7 +1199,7 @@ static struct int_queue *ehci_create_int_queue(struct usb_device *dev, /* hook up to periodic list */ result->last->qh_link = list->qh_link; - list->qh_link = cpu_to_hc32((unsigned long)result->first | QH_LINK_TYPE_QH); + list->qh_link = cpu_to_hc32(result->first_dma | QH_LINK_TYPE_QH); if (enable_periodic(ehci) < 0) { dev_err(&dev->dev, @@ -1177,8 +1211,10 @@ static struct int_queue *ehci_create_int_queue(struct usb_device *dev, dev_dbg(&dev->dev, "Exit create_int_queue\n"); return result; fail3: - dma_free_coherent(result->tds, 0, sizeof(struct qTD) * queuesize); - dma_free_coherent(result->first, 0, sizeof(struct QH) * queuesize); + dma_free_coherent(result->tds, result->tds_dma, + sizeof(struct qTD) * queuesize); + dma_free_coherent(result->first, result->first_dma, + sizeof(struct QH) * queuesize); free(result); return NULL; } @@ -1235,14 +1271,14 @@ static int ehci_destroy_int_queue(struct usb_device *dev, dev_dbg(&dev->dev, "considering %p, with qh_link %x\n", cur, cur->qh_link); - if (NEXT_QH(cur) == queue->first) { + if (NEXT_QH(queue, cur) == queue->first) { dev_dbg(&dev->dev, "found candidate. removing from chain\n"); cur->qh_link = queue->last->qh_link; result = 0; break; } - cur = NEXT_QH(cur); + cur = NEXT_QH(queue, cur); } if (ehci->periodic_schedules > 0) { @@ -1269,14 +1305,14 @@ submit_int_msg(struct usb_device *dev, unsigned long pipe, void *buffer, uint64_t start; void *backbuffer; int result = 0, ret; + dma_addr_t buffer_dma; dev_dbg(ehci->dev, "dev=%p, pipe=%lu, buffer=%p, length=%d, interval=%d", dev, pipe, buffer, length, interval); - dma_sync_single_for_device((unsigned long)buffer, length, - DMA_BIDIRECTIONAL); + buffer_dma = dma_map_single(ehci->dev, buffer, length, DMA_BIDIRECTIONAL); - queue = ehci_create_int_queue(dev, pipe, 1, length, buffer, interval); + queue = ehci_create_int_queue(dev, pipe, 1, length, buffer, buffer_dma, interval); if (!queue) return -EINVAL; @@ -1298,8 +1334,7 @@ submit_int_msg(struct usb_device *dev, unsigned long pipe, void *buffer, result = -EINVAL; } - dma_sync_single_for_cpu((unsigned long)buffer, length, - DMA_BIDIRECTIONAL); + dma_unmap_single(ehci->dev, buffer_dma, length, DMA_BIDIRECTIONAL); ret = ehci_destroy_int_queue(dev, queue); if (!result) @@ -1335,11 +1370,11 @@ struct ehci_host *ehci_register(struct device_d *dev, struct ehci_data *data) ehci->post_init = data->post_init; ehci->qh_list = dma_alloc_coherent(sizeof(struct QH) * NUM_QH, - DMA_ADDRESS_BROKEN); + &ehci->qh_list_dma); ehci->periodic_queue = dma_alloc_coherent(sizeof(struct QH), - DMA_ADDRESS_BROKEN); + &ehci->periodic_queue_dma); ehci->td = dma_alloc_coherent(sizeof(struct qTD) * NUM_TD, - DMA_ADDRESS_BROKEN); + &ehci->td_dma); host->hw_dev = dev; host->init = ehci_init; diff --git a/drivers/video/ssd1307fb.c b/drivers/video/ssd1307fb.c index 70077e43a8..835814bf53 100644 --- a/drivers/video/ssd1307fb.c +++ b/drivers/video/ssd1307fb.c @@ -405,8 +405,9 @@ static int ssd1307fb_probe(struct device_d *dev) } info = xzalloc(sizeof(struct fb_info)); + par = xzalloc(sizeof(*par)); - par = info->priv; + info->priv = par; par->info = info; par->client = client; @@ -414,12 +415,8 @@ static int ssd1307fb_probe(struct device_d *dev) par->reset = of_get_named_gpio(node, "reset-gpios", 0); - if (!gpio_is_valid(par->reset)) { - ret = par->reset; - if (ret != -EPROBE_DEFER) - dev_err(&client->dev, - "Couldn't get named gpio 'reset-gpios': %s.\n", - strerror(-ret)); + if (!gpio_is_valid(par->reset) && par->reset == -EPROBE_DEFER) { + ret = -EPROBE_DEFER; goto fb_alloc_error; } @@ -502,38 +499,41 @@ static int ssd1307fb_probe(struct device_d *dev) info->screen_base = (u8 __force __iomem *)vmem; - ret = gpio_request_one(par->reset, - GPIOF_OUT_INIT_HIGH, - "oled-reset"); - if (ret) { - dev_err(&client->dev, - "failed to request gpio %d: %d\n", - par->reset, ret); - goto reset_oled_error; - } - - if (par->vbat) { - ret = regulator_disable(par->vbat); - if (ret < 0) + if (par->reset >= 0) { + ret = gpio_request_one(par->reset, + GPIOF_OUT_INIT_HIGH, + "oled-reset"); + if (ret) { + dev_err(&client->dev, + "failed to request gpio %d: %d\n", + par->reset, ret); goto reset_oled_error; + } } - i2c_set_clientdata(client, info); + ret = regulator_disable(par->vbat); + if (ret < 0) + goto reset_oled_error; - /* Reset the screen */ - gpio_set_value(par->reset, 0); - udelay(4); + i2c_set_clientdata(client, info); - if (par->vbat) { - ret = regulator_enable(par->vbat); - if (ret < 0) - goto reset_oled_error; + if (par->reset > 0) { + /* Reset the screen */ + gpio_set_value(par->reset, 0); + udelay(4); } - mdelay(100); + ret = regulator_enable(par->vbat); + if (ret < 0) + goto reset_oled_error; - gpio_set_value(par->reset, 1); - udelay(4); + if (par->vbat) + mdelay(100); + + if (par->reset > 0) { + gpio_set_value(par->reset, 1); + udelay(4); + } ret = ssd1307fb_init(par); if (ret) @@ -574,6 +574,7 @@ reset_oled_error: free(vmem); fb_alloc_error: regulator_disable(par->vbat); + free(par); free(info); return ret; } |