struct esoc_desc *devm_register_esoc_client(struct device *dev, const char *name) { int ret, index; const char *client_desc; char *esoc_prop; const __be32 *parp; struct device_node *esoc_node; struct device_node *np = dev->of_node; struct esoc_clink *esoc_clink; struct esoc_desc *desc; char *esoc_name, *esoc_link; for (index = 0;; index++) { esoc_prop = kasprintf(GFP_KERNEL, "esoc-%d", index); parp = of_get_property(np, esoc_prop, NULL); if (parp == NULL) { dev_err(dev, "esoc device not present\n"); kfree(esoc_prop); return NULL; } ret = of_property_read_string_index(np, "esoc-names", index, &client_desc); if (ret) { dev_err(dev, "cannot find matching string\n"); kfree(esoc_prop); return NULL; } if (strcmp(client_desc, name)) { kfree(esoc_prop); continue; } kfree(esoc_prop); esoc_node = of_find_node_by_phandle(be32_to_cpup(parp)); esoc_clink = get_esoc_clink_by_node(esoc_node); if (IS_ERR_OR_NULL(esoc_clink)) { dev_err(dev, "matching esoc clink not present\n"); return ERR_PTR(-EPROBE_DEFER); } esoc_name = kasprintf(GFP_KERNEL, "esoc%d", esoc_clink->id); if (IS_ERR_OR_NULL(esoc_name)) { dev_err(dev, "unable to allocate esoc name\n"); return ERR_PTR(-ENOMEM); } esoc_link = kasprintf(GFP_KERNEL, "%s", esoc_clink->link_name); if (IS_ERR_OR_NULL(esoc_link)) { dev_err(dev, "unable to allocate esoc link name\n"); kfree(esoc_name); return ERR_PTR(-ENOMEM); } desc = devres_alloc(devm_esoc_desc_release, sizeof(*desc), GFP_KERNEL); if (IS_ERR_OR_NULL(desc)) { kfree(esoc_name); kfree(esoc_link); dev_err(dev, "unable to allocate esoc descriptor\n"); return ERR_PTR(-ENOMEM); } desc->name = esoc_name; desc->link = esoc_link; desc->priv = esoc_clink; devres_add(dev, desc); return desc; } return NULL; }
static int uniphier_system_bus_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct uniphier_system_bus_priv *priv; struct resource *regs; const __be32 *ranges; u32 cells, addr, size; u64 paddr; int pna, bank, rlen, rone, ret; priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); if (!priv) return -ENOMEM; regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); priv->membase = devm_ioremap_resource(dev, regs); if (IS_ERR(priv->membase)) return PTR_ERR(priv->membase); priv->dev = dev; pna = of_n_addr_cells(dev->of_node); ret = of_property_read_u32(dev->of_node, "#address-cells", &cells); if (ret) { dev_err(dev, "failed to get #address-cells\n"); return ret; } if (cells != 2) { dev_err(dev, "#address-cells must be 2\n"); return -EINVAL; } ret = of_property_read_u32(dev->of_node, "#size-cells", &cells); if (ret) { dev_err(dev, "failed to get #size-cells\n"); return ret; } if (cells != 1) { dev_err(dev, "#size-cells must be 1\n"); return -EINVAL; } ranges = of_get_property(dev->of_node, "ranges", &rlen); if (!ranges) { dev_err(dev, "failed to get ranges property\n"); return -ENOENT; } rlen /= sizeof(*ranges); rone = pna + 2; for (; rlen >= rone; rlen -= rone) { bank = be32_to_cpup(ranges++); addr = be32_to_cpup(ranges++); paddr = of_translate_address(dev->of_node, ranges); if (paddr == OF_BAD_ADDR) return -EINVAL; ranges += pna; size = be32_to_cpup(ranges++); ret = uniphier_system_bus_add_bank(priv, bank, addr, paddr, size); if (ret) return ret; } ret = uniphier_system_bus_check_overlap(priv); if (ret) return ret; uniphier_system_bus_check_boot_swap(priv); uniphier_system_bus_set_reg(priv); platform_set_drvdata(pdev, priv); /* Now, the bus is configured. Populate platform_devices below it */ return of_platform_default_populate(dev->of_node, NULL, dev); }
int nbd_receive_negotiate(int csock, const char *name, uint32_t *flags, off_t *size, size_t *blocksize) { char buf[256]; uint64_t magic, s; uint16_t tmp; TRACE("Receiving negotation."); if (read_sync(csock, buf, 8) != 8) { LOG("read failed"); errno = EINVAL; return -1; } buf[8] = '\0'; if (strlen(buf) == 0) { LOG("server connection closed"); errno = EINVAL; return -1; } TRACE("Magic is %c%c%c%c%c%c%c%c", qemu_isprint(buf[0]) ? buf[0] : '.', qemu_isprint(buf[1]) ? buf[1] : '.', qemu_isprint(buf[2]) ? buf[2] : '.', qemu_isprint(buf[3]) ? buf[3] : '.', qemu_isprint(buf[4]) ? buf[4] : '.', qemu_isprint(buf[5]) ? buf[5] : '.', qemu_isprint(buf[6]) ? buf[6] : '.', qemu_isprint(buf[7]) ? buf[7] : '.'); if (memcmp(buf, "NBDMAGIC", 8) != 0) { LOG("Invalid magic received"); errno = EINVAL; return -1; } if (read_sync(csock, &magic, sizeof(magic)) != sizeof(magic)) { LOG("read failed"); errno = EINVAL; return -1; } magic = be64_to_cpu(magic); TRACE("Magic is 0x%" PRIx64, magic); if (name) { uint32_t reserved = 0; uint32_t opt; uint32_t namesize; TRACE("Checking magic (opts_magic)"); if (magic != 0x49484156454F5054LL) { LOG("Bad magic received"); errno = EINVAL; return -1; } if (read_sync(csock, &tmp, sizeof(tmp)) != sizeof(tmp)) { LOG("flags read failed"); errno = EINVAL; return -1; } *flags = be16_to_cpu(tmp) << 16; /* reserved for future use */ if (write_sync(csock, &reserved, sizeof(reserved)) != sizeof(reserved)) { LOG("write failed (reserved)"); errno = EINVAL; return -1; } /* write the export name */ magic = cpu_to_be64(magic); if (write_sync(csock, &magic, sizeof(magic)) != sizeof(magic)) { LOG("write failed (magic)"); errno = EINVAL; return -1; } opt = cpu_to_be32(NBD_OPT_EXPORT_NAME); if (write_sync(csock, &opt, sizeof(opt)) != sizeof(opt)) { LOG("write failed (opt)"); errno = EINVAL; return -1; } namesize = cpu_to_be32(strlen(name)); if (write_sync(csock, &namesize, sizeof(namesize)) != sizeof(namesize)) { LOG("write failed (namesize)"); errno = EINVAL; return -1; } if (write_sync(csock, (char*)name, strlen(name)) != strlen(name)) { LOG("write failed (name)"); errno = EINVAL; return -1; } } else { TRACE("Checking magic (cli_magic)"); if (magic != 0x00420281861253LL) { LOG("Bad magic received"); errno = EINVAL; return -1; } } if (read_sync(csock, &s, sizeof(s)) != sizeof(s)) { LOG("read failed"); errno = EINVAL; return -1; } *size = be64_to_cpu(s); *blocksize = 1024; TRACE("Size is %" PRIu64, *size); if (!name) { if (read_sync(csock, flags, sizeof(*flags)) != sizeof(*flags)) { LOG("read failed (flags)"); errno = EINVAL; return -1; } *flags = be32_to_cpup(flags); } else { if (read_sync(csock, &tmp, sizeof(tmp)) != sizeof(tmp)) { LOG("read failed (tmp)"); errno = EINVAL; return -1; } *flags |= be32_to_cpu(tmp); } if (read_sync(csock, &buf, 124) != 124) { LOG("read failed (buf)"); errno = EINVAL; return -1; } return 0; }
void mmc_rpmb_post_frame(struct mmc_core_rpmb_req *rpmb_req) { int i; struct mmc_ioc_rpmb_req *p_req; __u8 *buf_frame; if (!rpmb_req || !rpmb_req->ready) return; p_req = rpmb_req->req; buf_frame = rpmb_req->frame; if (!p_req || !buf_frame) return; /* * Regarding to the check rules, here is the post * rules * All will return result. * GET_WRITE_COUNTER: * must: write counter, nonce * optional: MAC * WRITE_DATA: * must: MAC, write counter * READ_DATA: * must: nonce, data * optional: MAC * PROGRAM_KEY: * must: Nothing * * Except READ_DATA, all of these operations only need to parse * one frame. READ_DATA needs blks frames to get DATA */ memcpy(p_req->result, buf_frame + RPMB_RES_BEG, 2); *p_req->result = be16_to_cpup(p_req->result); if (p_req->type == RPMB_PROGRAM_KEY) goto out; if (p_req->type == RPMB_GET_WRITE_COUNTER || p_req->type == RPMB_WRITE_DATA) { memcpy(p_req->wc, buf_frame + RPMB_WCOUNTER_BEG, 4); *p_req->wc = be32_to_cpup(p_req->wc); } if (p_req->type == RPMB_GET_WRITE_COUNTER || p_req->type == RPMB_READ_DATA) { /* nonce copy */ memcpy(p_req->nonce, buf_frame + RPMB_NONCE_BEG, 16); } /* * Take MAC within the last package */ if (p_req->type == RPMB_READ_DATA) { __u8 *data = p_req->data; for (i = 0; i < p_req->blk_cnt; i++) { memcpy(data, buf_frame + i * 512 + RPMB_DATA_BEG, 256); data += 256; } /* * MAC stored in the last package */ if (p_req->mac) { i--; memcpy(p_req->mac, buf_frame + i * 512 + RPMB_MAC_BEG, 32); } } else if (p_req->mac) memcpy(p_req->mac, buf_frame + RPMB_MAC_BEG, 32); out: kfree(buf_frame); rpmb_req->frame = NULL; return; }
/** * of_irq_parse_raw - Low level interrupt tree parsing * @parent: the device interrupt parent * @addr: address specifier (start of "reg" property of the device) in be32 format * @out_irq: structure of_irq updated by this function * * Returns 0 on success and a negative number on error * * This function is a low-level interrupt tree walking function. It * can be used to do a partial walk with synthetized reg and interrupts * properties, for example when resolving PCI interrupts when no device * node exist for the parent. It takes an interrupt specifier structure as * input, walks the tree looking for any interrupt-map properties, translates * the specifier for each map, and then returns the translated map. */ int of_irq_parse_raw(const __be32 *addr, struct of_phandle_args *out_irq) { struct device_node *ipar, *tnode, *old = NULL, *newpar = NULL; __be32 initial_match_array[MAX_PHANDLE_ARGS]; const __be32 *match_array = initial_match_array; const __be32 *tmp, *imap, *imask, dummy_imask[] = { [0 ... MAX_PHANDLE_ARGS] = ~0 }; u32 intsize = 1, addrsize, newintsize = 0, newaddrsize = 0; int imaplen, match, i; #ifdef DEBUG of_print_phandle_args("of_irq_parse_raw: ", out_irq); #endif ipar = of_node_get(out_irq->np); /* First get the #interrupt-cells property of the current cursor * that tells us how to interpret the passed-in intspec. If there * is none, we are nice and just walk up the tree */ do { tmp = of_get_property(ipar, "#interrupt-cells", NULL); if (tmp != NULL) { intsize = be32_to_cpu(*tmp); break; } tnode = ipar; ipar = of_irq_find_parent(ipar); of_node_put(tnode); } while (ipar); if (ipar == NULL) { pr_debug(" -> no parent found !\n"); goto fail; } pr_debug("of_irq_parse_raw: ipar=%s, size=%d\n", of_node_full_name(ipar), intsize); if (out_irq->args_count != intsize) return -EINVAL; /* Look for this #address-cells. We have to implement the old linux * trick of looking for the parent here as some device-trees rely on it */ old = of_node_get(ipar); do { tmp = of_get_property(old, "#address-cells", NULL); tnode = of_get_parent(old); of_node_put(old); old = tnode; } while (old && tmp == NULL); of_node_put(old); old = NULL; addrsize = (tmp == NULL) ? 2 : be32_to_cpu(*tmp); pr_debug(" -> addrsize=%d\n", addrsize); /* Range check so that the temporary buffer doesn't overflow */ if (WARN_ON(addrsize + intsize > MAX_PHANDLE_ARGS)) goto fail; /* Precalculate the match array - this simplifies match loop */ for (i = 0; i < addrsize; i++) initial_match_array[i] = addr ? addr[i] : 0; for (i = 0; i < intsize; i++) initial_match_array[addrsize + i] = cpu_to_be32(out_irq->args[i]); /* Now start the actual "proper" walk of the interrupt tree */ while (ipar != NULL) { /* Now check if cursor is an interrupt-controller and if it is * then we are done */ if (of_get_property(ipar, "interrupt-controller", NULL) != NULL) { pr_debug(" -> got it !\n"); return 0; } /* * interrupt-map parsing does not work without a reg * property when #address-cells != 0 */ if (addrsize && !addr) { pr_debug(" -> no reg passed in when needed !\n"); goto fail; } /* Now look for an interrupt-map */ imap = of_get_property(ipar, "interrupt-map", &imaplen); /* No interrupt map, check for an interrupt parent */ if (imap == NULL) { pr_debug(" -> no map, getting parent\n"); newpar = of_irq_find_parent(ipar); goto skiplevel; } imaplen /= sizeof(u32); /* Look for a mask */ imask = of_get_property(ipar, "interrupt-map-mask", NULL); if (!imask) imask = dummy_imask; /* Parse interrupt-map */ match = 0; while (imaplen > (addrsize + intsize + 1) && !match) { /* Compare specifiers */ match = 1; for (i = 0; i < (addrsize + intsize); i++, imaplen--) match &= !((match_array[i] ^ *imap++) & imask[i]); pr_debug(" -> match=%d (imaplen=%d)\n", match, imaplen); /* Get the interrupt parent */ if (of_irq_workarounds & OF_IMAP_NO_PHANDLE) newpar = of_node_get(of_irq_dflt_pic); else newpar = of_find_node_by_phandle(be32_to_cpup(imap)); imap++; --imaplen; /* Check if not found */ if (newpar == NULL) { pr_debug(" -> imap parent not found !\n"); goto fail; } /* Get #interrupt-cells and #address-cells of new * parent */ tmp = of_get_property(newpar, "#interrupt-cells", NULL); if (tmp == NULL) { pr_debug(" -> parent lacks #interrupt-cells!\n"); goto fail; } newintsize = be32_to_cpu(*tmp); tmp = of_get_property(newpar, "#address-cells", NULL); newaddrsize = (tmp == NULL) ? 0 : be32_to_cpu(*tmp); pr_debug(" -> newintsize=%d, newaddrsize=%d\n", newintsize, newaddrsize); /* Check for malformed properties */ if (WARN_ON(newaddrsize + newintsize > MAX_PHANDLE_ARGS)) goto fail; if (imaplen < (newaddrsize + newintsize)) goto fail; imap += newaddrsize + newintsize; imaplen -= newaddrsize + newintsize; pr_debug(" -> imaplen=%d\n", imaplen); } if (!match) goto fail; /* * Successfully parsed an interrrupt-map translation; copy new * interrupt specifier into the out_irq structure */ out_irq->np = newpar; match_array = imap - newaddrsize - newintsize; for (i = 0; i < newintsize; i++) out_irq->args[i] = be32_to_cpup(imap - newintsize + i); out_irq->args_count = intsize = newintsize; addrsize = newaddrsize; skiplevel: /* Iterate again with new parent */ pr_debug(" -> new parent: %s\n", of_node_full_name(newpar)); of_node_put(ipar); ipar = newpar; newpar = NULL; } fail: of_node_put(ipar); of_node_put(newpar); return -EINVAL; }
static int __init opal_init(void) { struct device_node *np, *consoles; const __be32 *irqs; int rc, i, irqlen; opal_node = of_find_node_by_path("/ibm,opal"); if (!opal_node) { pr_warn("opal: Node not found\n"); return -ENODEV; } /* Register OPAL consoles if any ports */ if (firmware_has_feature(FW_FEATURE_OPALv2)) consoles = of_find_node_by_path("/ibm,opal/consoles"); else consoles = of_node_get(opal_node); if (consoles) { for_each_child_of_node(consoles, np) { if (strcmp(np->name, "serial")) continue; of_platform_device_create(np, NULL, NULL); } of_node_put(consoles); } /* Find all OPAL interrupts and request them */ irqs = of_get_property(opal_node, "opal-interrupts", &irqlen); pr_debug("opal: Found %d interrupts reserved for OPAL\n", irqs ? (irqlen / 4) : 0); opal_irq_count = irqlen / 4; opal_irqs = kzalloc(opal_irq_count * sizeof(unsigned int), GFP_KERNEL); for (i = 0; irqs && i < (irqlen / 4); i++, irqs++) { unsigned int hwirq = be32_to_cpup(irqs); unsigned int irq = irq_create_mapping(NULL, hwirq); if (irq == NO_IRQ) { pr_warning("opal: Failed to map irq 0x%x\n", hwirq); continue; } rc = request_irq(irq, opal_interrupt, 0, "opal", NULL); if (rc) pr_warning("opal: Error %d requesting irq %d" " (0x%x)\n", rc, irq, hwirq); opal_irqs[i] = irq; } /* Create "opal" kobject under /sys/firmware */ rc = opal_sysfs_init(); if (rc == 0) { /* Setup dump region interface */ opal_dump_region_init(); /* Setup error log interface */ rc = opal_elog_init(); /* Setup code update interface */ opal_flash_init(); /* Setup platform dump extract interface */ opal_platform_dump_init(); /* Setup system parameters interface */ opal_sys_param_init(); /* Setup message log interface. */ opal_msglog_init(); } return 0; }
static int mlx4_ib_query_device(struct ib_device *ibdev, struct ib_device_attr *props) { struct mlx4_ib_dev *dev = to_mdev(ibdev); struct ib_smp *in_mad = NULL; struct ib_smp *out_mad = NULL; int err = -ENOMEM; in_mad = kzalloc(sizeof *in_mad, GFP_KERNEL); out_mad = kmalloc(sizeof *out_mad, GFP_KERNEL); if (!in_mad || !out_mad) goto out; init_query_mad(in_mad); in_mad->attr_id = IB_SMP_ATTR_NODE_INFO; err = mlx4_MAD_IFC(to_mdev(ibdev), 1, 1, 1, NULL, NULL, in_mad, out_mad); if (err) goto out; memset(props, 0, sizeof *props); props->fw_ver = dev->dev->caps.fw_ver; props->device_cap_flags = IB_DEVICE_CHANGE_PHY_PORT | IB_DEVICE_PORT_ACTIVE_EVENT | IB_DEVICE_SYS_IMAGE_GUID | IB_DEVICE_RC_RNR_NAK_GEN | IB_DEVICE_BLOCK_MULTICAST_LOOPBACK; if (dev->dev->caps.flags & MLX4_DEV_CAP_FLAG_BAD_PKEY_CNTR) props->device_cap_flags |= IB_DEVICE_BAD_PKEY_CNTR; if (dev->dev->caps.flags & MLX4_DEV_CAP_FLAG_BAD_QKEY_CNTR) props->device_cap_flags |= IB_DEVICE_BAD_QKEY_CNTR; if (dev->dev->caps.flags & MLX4_DEV_CAP_FLAG_APM) props->device_cap_flags |= IB_DEVICE_AUTO_PATH_MIG; if (dev->dev->caps.flags & MLX4_DEV_CAP_FLAG_UD_AV_PORT) props->device_cap_flags |= IB_DEVICE_UD_AV_PORT_ENFORCE; if (dev->dev->caps.flags & MLX4_DEV_CAP_FLAG_IPOIB_CSUM) props->device_cap_flags |= IB_DEVICE_UD_IP_CSUM; if (dev->dev->caps.max_gso_sz && dev->dev->caps.flags & MLX4_DEV_CAP_FLAG_BLH) props->device_cap_flags |= IB_DEVICE_UD_TSO; if (dev->dev->caps.bmme_flags & MLX4_BMME_FLAG_RESERVED_LKEY) props->device_cap_flags |= IB_DEVICE_LOCAL_DMA_LKEY; if ((dev->dev->caps.bmme_flags & MLX4_BMME_FLAG_LOCAL_INV) && (dev->dev->caps.bmme_flags & MLX4_BMME_FLAG_REMOTE_INV) && (dev->dev->caps.bmme_flags & MLX4_BMME_FLAG_FAST_REG_WR)) props->device_cap_flags |= IB_DEVICE_MEM_MGT_EXTENSIONS; if (dev->dev->caps.flags & MLX4_DEV_CAP_FLAG_XRC) props->device_cap_flags |= IB_DEVICE_XRC; props->vendor_id = be32_to_cpup((__be32 *) (out_mad->data + 36)) & 0xffffff; props->vendor_part_id = be16_to_cpup((__be16 *) (out_mad->data + 30)); props->hw_ver = be32_to_cpup((__be32 *) (out_mad->data + 32)); memcpy(&props->sys_image_guid, out_mad->data + 4, 8); props->max_mr_size = ~0ull; props->page_size_cap = dev->dev->caps.page_size_cap; props->max_qp = dev->dev->caps.num_qps - dev->dev->caps.reserved_qps; props->max_qp_wr = dev->dev->caps.max_wqes; props->max_sge = min(dev->dev->caps.max_sq_sg, dev->dev->caps.max_rq_sg); props->max_cq = dev->dev->caps.num_cqs - dev->dev->caps.reserved_cqs; props->max_cqe = dev->dev->caps.max_cqes; props->max_mr = dev->dev->caps.num_mpts - dev->dev->caps.reserved_mrws; props->max_pd = dev->dev->caps.num_pds - dev->dev->caps.reserved_pds; props->max_qp_rd_atom = dev->dev->caps.max_qp_dest_rdma; props->max_qp_init_rd_atom = dev->dev->caps.max_qp_init_rdma; props->max_res_rd_atom = props->max_qp_rd_atom * props->max_qp; props->max_srq = dev->dev->caps.num_srqs - dev->dev->caps.reserved_srqs; props->max_srq_wr = dev->dev->caps.max_srq_wqes - 1; props->max_srq_sge = dev->dev->caps.max_srq_sge; props->max_fast_reg_page_list_len = MLX4_MAX_FAST_REG_PAGES; props->local_ca_ack_delay = dev->dev->caps.local_ca_ack_delay; props->atomic_cap = dev->dev->caps.flags & MLX4_DEV_CAP_FLAG_ATOMIC ? IB_ATOMIC_HCA : IB_ATOMIC_NONE; props->masked_atomic_cap = IB_ATOMIC_HCA; props->max_pkeys = dev->dev->caps.pkey_table_len[1]; props->max_mcast_grp = dev->dev->caps.num_mgms + dev->dev->caps.num_amgms; props->max_mcast_qp_attach = dev->dev->caps.num_qp_per_mgm; props->max_total_mcast_qp_attach = props->max_mcast_qp_attach * props->max_mcast_grp; props->max_map_per_fmr = dev->dev->caps.max_fmr_maps; out: kfree(in_mad); kfree(out_mad); return err; }
/** * of_mdiobus_register - Register mii_bus and create PHYs from the device tree * @mdio: pointer to mii_bus structure * @np: pointer to device_node of MDIO bus. * * This function registers the mii_bus structure and registers a phy_device * for each child node of @np. */ int of_mdiobus_register(struct mii_bus *mdio, struct device_node *np) { struct phy_device *phy; struct device_node *child; int rc, i; /* Mask out all PHYs from auto probing. Instead the PHYs listed in * the device tree are populated after the bus has been registered */ mdio->phy_mask = ~0; /* Clear all the IRQ properties */ if (mdio->irq) for (i=0; i<PHY_MAX_ADDR; i++) mdio->irq[i] = PHY_POLL; mdio->dev.of_node = np; /* Register the MDIO bus */ rc = mdiobus_register(mdio); if (rc) return rc; /* Loop over the child nodes and register a phy_device for each one */ for_each_available_child_of_node(np, child) { const __be32 *paddr; u32 addr; int len; bool is_c45; /* A PHY must have a reg property in the range [0-31] */ paddr = of_get_property(child, "reg", &len); if (!paddr || len < sizeof(*paddr)) { dev_err(&mdio->dev, "%s has invalid PHY address\n", child->full_name); continue; } addr = be32_to_cpup(paddr); if (addr >= 32) { dev_err(&mdio->dev, "%s PHY address %i is too large\n", child->full_name, addr); continue; } if (mdio->irq) { mdio->irq[addr] = irq_of_parse_and_map(child, 0); if (!mdio->irq[addr]) mdio->irq[addr] = PHY_POLL; } is_c45 = of_device_is_compatible(child, "ethernet-phy-ieee802.3-c45"); phy = get_phy_device(mdio, addr, is_c45); if (!phy || IS_ERR(phy)) { phy = phy_device_create(mdio, addr, 0, false, NULL); if (!phy || IS_ERR(phy)) { dev_err(&mdio->dev, "error creating PHY at address %i\n", addr); continue; } } /* Associate the OF node with the device structure so it * can be looked up later */ of_node_get(child); phy->dev.of_node = child; /* All data is now stored in the phy struct; register it */ rc = phy_device_register(phy); if (rc) { phy_device_free(phy); of_node_put(child); continue; } dev_dbg(&mdio->dev, "registered phy %s at address %i\n", child->name, addr); } return 0; }
static int zynq_rpmsg_retrieve_dts_info(struct platform_device *pdev) { const void *of_prop; struct resource *res; /* Retrieve memory information. */ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) { dev_err(&pdev->dev, "invalid address\n"); return -ENODEV; } zynq_rpmsg_p->mem_start = res->start; zynq_rpmsg_p->mem_end = res->end; /* Allocate free IPI number */ of_prop = of_get_property(pdev->dev.of_node, "vring0", NULL); if (!of_prop) { dev_err(&pdev->dev, "Please specify vring0 node property\n"); return -ENODEV; } zynq_rpmsg_p->vring0 = be32_to_cpup(of_prop); /* Read vring1 ipi number */ of_prop = of_get_property(pdev->dev.of_node, "vring1", NULL); if (!of_prop) { dev_err(&pdev->dev, "Please specify vring1 node property\n"); return -ENODEV; } zynq_rpmsg_p->vring1 = be32_to_cpup(of_prop); of_prop = of_get_property(pdev->dev.of_node, "num-descs", NULL); if (!of_prop) { dev_err(&pdev->dev, "Please specify num descs node property\n"); return -ENODEV; } zynq_rpmsg_p->num_descs = be32_to_cpup(of_prop); /* Read dev-feature */ of_prop = of_get_property(pdev->dev.of_node, "dev-feature", NULL); if (!of_prop) { dev_err(&pdev->dev, "Please specify dev features node property\n"); return -ENODEV; } zynq_rpmsg_p->dev_feature = be32_to_cpup(of_prop); /* Read gen-feature */ of_prop = of_get_property(pdev->dev.of_node, "gen-feature", NULL); if (!of_prop) { dev_err(&pdev->dev, "Please specify gen features node property\n"); return -ENODEV; } zynq_rpmsg_p->gen_feature = be32_to_cpup(of_prop); /* Read number of vrings */ of_prop = of_get_property(pdev->dev.of_node, "num-vrings", NULL); if (!of_prop) { dev_err(&pdev->dev, "Please specify num-vrings node property\n"); return -ENODEV; } zynq_rpmsg_p->num_vrings = be32_to_cpup(of_prop); if (zynq_rpmsg_p->num_vrings > 2) { dev_err(&pdev->dev, "We do not currently support more than 2 vrings.\n"); return -ENODEV; } /* Read vring alignment */ of_prop = of_get_property(pdev->dev.of_node, "alignment", NULL); if (!of_prop) { dev_err(&pdev->dev, "Please specify alignment node property\n"); return -ENODEV; } zynq_rpmsg_p->align = be32_to_cpup(of_prop); /* Read virtio ID*/ of_prop = of_get_property(pdev->dev.of_node, "virtioid", NULL); if (!of_prop) { dev_err(&pdev->dev, "Please specify virtio id property\n"); return -ENODEV; } zynq_rpmsg_p->virtioid = be32_to_cpup(of_prop); /* Read Ring Tx address. */ of_prop = of_get_property(pdev->dev.of_node, "ringtx", NULL); if (!of_prop) { dev_err(&pdev->dev, "Please specify ring tx property\n"); return -ENODEV; } zynq_rpmsg_p->ringtx = be32_to_cpup(of_prop); /* Read Ring Rx address. */ of_prop = of_get_property(pdev->dev.of_node, "ringrx", NULL); if (!of_prop) { dev_err(&pdev->dev, "Please specify ringrx property\n"); return -ENODEV; } zynq_rpmsg_p->ringrx = be32_to_cpup(of_prop); return 0; }
/** * svc_rdma_xdr_decode_req - Parse incoming RPC-over-RDMA header * @rq_arg: Receive buffer * * On entry, xdr->head[0].iov_base points to first byte in the * RPC-over-RDMA header. * * On successful exit, head[0] points to first byte past the * RPC-over-RDMA header. For RDMA_MSG, this is the RPC message. * The length of the RPC-over-RDMA header is returned. */ int svc_rdma_xdr_decode_req(struct xdr_buf *rq_arg) { __be32 *p, *end, *rdma_argp; unsigned int hdr_len; /* Verify that there's enough bytes for header + something */ if (rq_arg->len <= RPCRDMA_HDRLEN_ERR) goto out_short; rdma_argp = rq_arg->head[0].iov_base; if (*(rdma_argp + 1) != rpcrdma_version) goto out_version; switch (*(rdma_argp + 3)) { case rdma_msg: case rdma_nomsg: break; case rdma_done: goto out_drop; case rdma_error: goto out_drop; default: goto out_proc; } end = (__be32 *)((unsigned long)rdma_argp + rq_arg->len); p = xdr_check_read_list(rdma_argp + 4, end); if (!p) goto out_inval; p = xdr_check_write_list(p, end); if (!p) goto out_inval; p = xdr_check_reply_chunk(p, end); if (!p) goto out_inval; if (p > end) goto out_inval; rq_arg->head[0].iov_base = p; hdr_len = (unsigned long)p - (unsigned long)rdma_argp; rq_arg->head[0].iov_len -= hdr_len; return hdr_len; out_short: dprintk("svcrdma: header too short = %d\n", rq_arg->len); return -EINVAL; out_version: dprintk("svcrdma: bad xprt version: %u\n", be32_to_cpup(rdma_argp + 1)); return -EPROTONOSUPPORT; out_drop: dprintk("svcrdma: dropping RDMA_DONE/ERROR message\n"); return 0; out_proc: dprintk("svcrdma: bad rdma procedure (%u)\n", be32_to_cpup(rdma_argp + 3)); return -EINVAL; out_inval: dprintk("svcrdma: failed to parse transport header\n"); return -EINVAL; }
static int __devinit sdhci_of_probe(struct platform_device *ofdev) { const struct of_device_id *match; struct device_node *np = ofdev->dev.of_node; struct sdhci_of_data *sdhci_of_data; struct sdhci_host *host; struct sdhci_of_host *of_host; const __be32 *clk; int size; int ret; match = of_match_device(sdhci_of_match, &ofdev->dev); if (!match) return -EINVAL; sdhci_of_data = match->data; if (!of_device_is_available(np)) return -ENODEV; host = sdhci_alloc_host(&ofdev->dev, sizeof(*of_host)); if (IS_ERR(host)) return -ENOMEM; of_host = sdhci_priv(host); dev_set_drvdata(&ofdev->dev, host); host->ioaddr = of_iomap(np, 0); if (!host->ioaddr) { ret = -ENOMEM; goto err_addr_map; } host->irq = irq_of_parse_and_map(np, 0); if (!host->irq) { ret = -EINVAL; goto err_no_irq; } host->hw_name = dev_name(&ofdev->dev); if (sdhci_of_data) { host->quirks = sdhci_of_data->quirks; host->ops = &sdhci_of_data->ops; } if (of_get_property(np, "sdhci,auto-cmd12", NULL)) host->quirks |= SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12; if (of_get_property(np, "sdhci,1-bit-only", NULL)) host->quirks |= SDHCI_QUIRK_FORCE_1_BIT_DATA; if (sdhci_of_wp_inverted(np)) host->quirks |= SDHCI_QUIRK_INVERTED_WRITE_PROTECT; clk = of_get_property(np, "clock-frequency", &size); if (clk && size == sizeof(*clk) && *clk) of_host->clock = be32_to_cpup(clk); ret = sdhci_add_host(host); if (ret) goto err_add_host; return 0; err_add_host: irq_dispose_mapping(host->irq); err_no_irq: iounmap(host->ioaddr); err_addr_map: sdhci_free_host(host); return ret; }
static int imx6q_cpufreq_probe(struct platform_device *pdev) { struct device_node *np; struct dev_pm_opp *opp; unsigned long min_volt, max_volt; int num, ret; const struct property *prop; const __be32 *val; u32 nr, i, j; cpu_dev = get_cpu_device(0); if (!cpu_dev) { pr_err("failed to get cpu0 device\n"); return -ENODEV; } np = of_node_get(cpu_dev->of_node); if (!np) { dev_err(cpu_dev, "failed to find cpu0 node\n"); return -ENOENT; } arm_clk = clk_get(cpu_dev, "arm"); pll1_sys_clk = clk_get(cpu_dev, "pll1_sys"); pll1_sw_clk = clk_get(cpu_dev, "pll1_sw"); step_clk = clk_get(cpu_dev, "step"); pll2_pfd2_396m_clk = clk_get(cpu_dev, "pll2_pfd2_396m"); if (IS_ERR(arm_clk) || IS_ERR(pll1_sys_clk) || IS_ERR(pll1_sw_clk) || IS_ERR(step_clk) || IS_ERR(pll2_pfd2_396m_clk)) { dev_err(cpu_dev, "failed to get clocks\n"); ret = -ENOENT; goto put_clk; } arm_reg = regulator_get(cpu_dev, "arm"); pu_reg = regulator_get_optional(cpu_dev, "pu"); soc_reg = regulator_get(cpu_dev, "soc"); if (IS_ERR(arm_reg) || IS_ERR(soc_reg)) { dev_err(cpu_dev, "failed to get regulators\n"); ret = -ENOENT; goto put_reg; } /* * We expect an OPP table supplied by platform. * Just, incase the platform did not supply the OPP * table, it will try to get it. */ num = dev_pm_opp_get_opp_count(cpu_dev); if (num < 0) { ret = dev_pm_opp_of_add_table(cpu_dev); if (ret < 0) { dev_err(cpu_dev, "failed to init OPP table: %d\n", ret); goto put_reg; } /* Because we have added the OPPs here, we must free them */ free_opp = true; num = dev_pm_opp_get_opp_count(cpu_dev); if (num < 0) { ret = num; dev_err(cpu_dev, "no OPP table is found: %d\n", ret); goto out_free_opp; } } ret = dev_pm_opp_init_cpufreq_table(cpu_dev, &freq_table); if (ret) { dev_err(cpu_dev, "failed to init cpufreq table: %d\n", ret); goto put_reg; } /* Make imx6_soc_volt array's size same as arm opp number */ imx6_soc_volt = devm_kzalloc(cpu_dev, sizeof(*imx6_soc_volt) * num, GFP_KERNEL); if (imx6_soc_volt == NULL) { ret = -ENOMEM; goto free_freq_table; } prop = of_find_property(np, "fsl,soc-operating-points", NULL); if (!prop || !prop->value) goto soc_opp_out; /* * Each OPP is a set of tuples consisting of frequency and * voltage like <freq-kHz vol-uV>. */ nr = prop->length / sizeof(u32); if (nr % 2 || (nr / 2) < num) goto soc_opp_out; for (j = 0; j < num; j++) { val = prop->value; for (i = 0; i < nr / 2; i++) { unsigned long freq = be32_to_cpup(val++); unsigned long volt = be32_to_cpup(val++); if (freq_table[j].frequency == freq) { imx6_soc_volt[soc_opp_count++] = volt; break; } } } soc_opp_out: /* use fixed soc opp volt if no valid soc opp info found in dtb */ if (soc_opp_count != num) { dev_warn(cpu_dev, "can NOT find valid fsl,soc-operating-points property in dtb, use default value!\n"); for (j = 0; j < num; j++) imx6_soc_volt[j] = PU_SOC_VOLTAGE_NORMAL; if (freq_table[num - 1].frequency * 1000 == FREQ_1P2_GHZ) imx6_soc_volt[num - 1] = PU_SOC_VOLTAGE_HIGH; } if (of_property_read_u32(np, "clock-latency", &transition_latency)) transition_latency = CPUFREQ_ETERNAL; /* * Calculate the ramp time for max voltage change in the * VDDSOC and VDDPU regulators. */ ret = regulator_set_voltage_time(soc_reg, imx6_soc_volt[0], imx6_soc_volt[num - 1]); if (ret > 0) transition_latency += ret * 1000; if (!IS_ERR(pu_reg)) { ret = regulator_set_voltage_time(pu_reg, imx6_soc_volt[0], imx6_soc_volt[num - 1]); if (ret > 0) transition_latency += ret * 1000; } /* * OPP is maintained in order of increasing frequency, and * freq_table initialised from OPP is therefore sorted in the * same order. */ rcu_read_lock(); opp = dev_pm_opp_find_freq_exact(cpu_dev, freq_table[0].frequency * 1000, true); min_volt = dev_pm_opp_get_voltage(opp); opp = dev_pm_opp_find_freq_exact(cpu_dev, freq_table[--num].frequency * 1000, true); max_volt = dev_pm_opp_get_voltage(opp); rcu_read_unlock(); ret = regulator_set_voltage_time(arm_reg, min_volt, max_volt); if (ret > 0) transition_latency += ret * 1000; ret = cpufreq_register_driver(&imx6q_cpufreq_driver); if (ret) { dev_err(cpu_dev, "failed register driver: %d\n", ret); goto free_freq_table; } of_node_put(np); return 0; free_freq_table: dev_pm_opp_free_cpufreq_table(cpu_dev, &freq_table); out_free_opp: if (free_opp) dev_pm_opp_of_remove_table(cpu_dev); put_reg: if (!IS_ERR(arm_reg)) regulator_put(arm_reg); if (!IS_ERR(pu_reg)) regulator_put(pu_reg); if (!IS_ERR(soc_reg)) regulator_put(soc_reg); put_clk: if (!IS_ERR(arm_clk)) clk_put(arm_clk); if (!IS_ERR(pll1_sys_clk)) clk_put(pll1_sys_clk); if (!IS_ERR(pll1_sw_clk)) clk_put(pll1_sw_clk); if (!IS_ERR(step_clk)) clk_put(step_clk); if (!IS_ERR(pll2_pfd2_396m_clk)) clk_put(pll2_pfd2_396m_clk); of_node_put(np); return ret; }
static void indirect_access_pixis_probe(void) { struct device_node *lbc_node; struct device_node *law_node; struct fsl_lbc_regs *lbc; void *ecm = NULL; phys_addr_t cs0_addr, cs1_addr; u32 br0, or0, br1, or1; const __be32 *iprop; unsigned int num_laws; lbc_node = of_find_compatible_node(NULL, NULL, "fsl,p1022-elbc"); if (!lbc_node) { pr_err("p1022ds: missing localbus node\n"); return; } lbc = of_iomap(lbc_node, 0); of_node_put(lbc_node); if (!lbc) { pr_err("p1022ds: could not map localbus node\n"); return; } law_node = of_find_compatible_node(NULL, NULL, "fsl,ecm-law"); if (!law_node) { pr_err("p1022ds: missing local access window node\n"); goto exit; } ecm = of_iomap(law_node, 0); if (!ecm) { pr_err("p1022ds: could not map local access window node\n"); goto exit; } iprop = of_get_property(law_node, "fsl,num-laws", NULL); if (!iprop) { pr_err("p1022ds: LAW node is missing fsl,num-laws property\n"); goto exit; } num_laws = be32_to_cpup(iprop); /* * Indirect mode requires both BR0 and BR1 to be set to "GPCM", * otherwise writes to these addresses won't actually appear on the * local bus, and so the PIXIS won't see them. * * In FCM mode, writes go to the NAND controller, which does not pass * them to the localbus directly. So we force BR0 and BR1 into GPCM * mode, since we don't care about what's behind the localbus any * more. */ br0 = in_be32(&lbc->bank[0].br); br1 = in_be32(&lbc->bank[1].br); or0 = in_be32(&lbc->bank[0].or); or1 = in_be32(&lbc->bank[1].or); /* Make sure CS0 and CS1 are programmed */ if (!(br0 & BR_V) || !(br1 & BR_V)) { pr_err("p1022ds: CS0 and/or CS1 is not programmed\n"); goto exit; } /* * Use the existing BRx/ORx values if it's already GPCM. Otherwise, * force the values to simple 32KB GPCM windows with the most * conservative timing. */ if ((br0 & BR_MSEL) != BR_MS_GPCM) { br0 = (br0 & BR_BA) | BR_V; or0 = 0xFFFF8000 | 0xFF7; out_be32(&lbc->bank[0].br, br0); out_be32(&lbc->bank[0].or, or0); } if ((br1 & BR_MSEL) != BR_MS_GPCM) { br1 = (br1 & BR_BA) | BR_V; or1 = 0xFFFF8000 | 0xFF7; out_be32(&lbc->bank[1].br, br1); out_be32(&lbc->bank[1].or, or1); } cs0_addr = lbc_br_to_phys(ecm, num_laws, br0); if (!cs0_addr) { pr_err("p1022ds: could not determine physical address for CS0" " (BR0=%08x)\n", br0); goto exit; } cs1_addr = lbc_br_to_phys(ecm, num_laws, br1); if (!cs1_addr) { pr_err("p1022ds: could not determine physical address for CS1" " (BR1=%08x)\n", br1); goto exit; } lbc_lcs0_ba = ioremap(cs0_addr, 1); if (!lbc_lcs0_ba) { pr_err("p1022ds: could not ioremap CS0 address %llx\n", (unsigned long long)cs0_addr); goto exit; } lbc_lcs1_ba = ioremap(cs1_addr, 1); if (!lbc_lcs1_ba) { pr_err("p1022ds: could not ioremap CS1 address %llx\n", (unsigned long long)cs1_addr); iounmap(lbc_lcs0_ba); } exit: if (ecm) iounmap(ecm); if (lbc) iounmap(lbc); if (law_node) of_node_put(law_node); }
static int fsl_ssi_probe(struct platform_device *pdev) { struct fsl_ssi_private *ssi_private; int ret = 0; struct device_attribute *dev_attr = NULL; struct device_node *np = pdev->dev.of_node; const char *p, *sprop; const uint32_t *iprop; struct resource res; char name[64]; /* SSIs that are not connected on the board should have a * status = "disabled" * property in their device tree nodes. */ if (!of_device_is_available(np)) return -ENODEV; /* The DAI name is the last part of the full name of the node. */ p = strrchr(np->full_name, '/') + 1; ssi_private = kzalloc(sizeof(struct fsl_ssi_private) + strlen(p), GFP_KERNEL); if (!ssi_private) { dev_err(&pdev->dev, "could not allocate DAI object\n"); return -ENOMEM; } strcpy(ssi_private->name, p); /* Initialize this copy of the CPU DAI driver structure */ memcpy(&ssi_private->cpu_dai_drv, &fsl_ssi_dai_template, sizeof(fsl_ssi_dai_template)); ssi_private->cpu_dai_drv.name = ssi_private->name; /* Get the addresses and IRQ */ ret = of_address_to_resource(np, 0, &res); if (ret) { dev_err(&pdev->dev, "could not determine device resources\n"); goto error_kmalloc; } ssi_private->ssi = of_iomap(np, 0); if (!ssi_private->ssi) { dev_err(&pdev->dev, "could not map device resources\n"); ret = -ENOMEM; goto error_kmalloc; } ssi_private->ssi_phys = res.start; ssi_private->irq = irq_of_parse_and_map(np, 0); if (ssi_private->irq == NO_IRQ) { dev_err(&pdev->dev, "no irq for node %s\n", np->full_name); ret = -ENXIO; goto error_iomap; } /* The 'name' should not have any slashes in it. */ ret = request_irq(ssi_private->irq, fsl_ssi_isr, 0, ssi_private->name, ssi_private); if (ret < 0) { dev_err(&pdev->dev, "could not claim irq %u\n", ssi_private->irq); goto error_irqmap; } /* Are the RX and the TX clocks locked? */ if (!of_find_property(np, "fsl,ssi-asynchronous", NULL)) { ssi_private->cpu_dai_drv.symmetric_rates = 1; ssi_private->cpu_dai_drv.symmetric_channels = 1; ssi_private->cpu_dai_drv.symmetric_samplebits = 1; } /* Determine the FIFO depth. */ iprop = of_get_property(np, "fsl,fifo-depth", NULL); if (iprop) ssi_private->fifo_depth = be32_to_cpup(iprop); else /* Older 8610 DTs didn't have the fifo-depth property */ ssi_private->fifo_depth = 8; ssi_private->baudclk_locked = false; spin_lock_init(&ssi_private->baudclk_lock); if (of_device_is_compatible(pdev->dev.of_node, "fsl,imx21-ssi")) { ssi_private->ssi_on_imx = true; ssi_private->coreclk = devm_clk_get(&pdev->dev, "ipg"); if (IS_ERR(ssi_private->coreclk)) { ret = PTR_ERR(ssi_private->coreclk); dev_err(&pdev->dev, "could not get ipg clock: %d\n", ret); goto error_irq; } ssi_private->clk = devm_clk_get(&pdev->dev, "baud"); if (IS_ERR(ssi_private->clk)) { ret = PTR_ERR(ssi_private->clk); dev_err(&pdev->dev, "could not get baud clock: %d\n", ret); goto error_irq; } /* * We have burstsize be "fifo_depth - 2" to match the SSI * watermark setting in fsl_ssi_startup(). */ ssi_private->dma_params_tx.maxburst = ssi_private->fifo_depth - 2; ssi_private->dma_params_rx.maxburst = ssi_private->fifo_depth - 2; ssi_private->dma_params_tx.addr = ssi_private->ssi_phys + offsetof(struct ccsr_ssi, stx0); ssi_private->dma_params_rx.addr = ssi_private->ssi_phys + offsetof(struct ccsr_ssi, srx0); }
int __init cma_reserve_mem_fdt_scan(unsigned long node, const char *uname, int depth, void *data) { static int found; phys_addr_t base, size; int len; int sec_prot = 0; int dynamic_prot = 0; const __be32 *prop; unsigned long size_cells = dt_root_size_cells; unsigned long addr_cells = dt_root_addr_cells; char *status; char *cma_name = NULL; if (!found && depth == 1 && strcmp(uname, "reserved-memory") == 0) { prop = of_get_flat_dt_prop(node, "#size-cells", NULL); if (prop) size_cells = be32_to_cpup(prop); prop = of_get_flat_dt_prop(node, "#address-cells", NULL); if (prop) addr_cells = be32_to_cpup(prop); found = 1; /* scan next node */ return 0; } else if (!found) { /* scan next node */ return 0; } else if (found && depth < 2) { /* scanning of /reserved-memory has been finished */ return 1; } status = (char *)of_get_flat_dt_prop(node, "status", NULL); /* * Yes, we actually want strncmp here to check for a prefix * ok vs. okay */ if (status && (strncmp(status, "ok", 2) != 0)) return 0; if (!of_get_flat_dt_prop(node, "hisi,cma-mem", NULL)) return 0; if (of_get_flat_dt_prop(node, "hisi,sec-mem", NULL)) sec_prot = 1; if (of_get_flat_dt_prop(node, "hisi,cma-dynamic", NULL)) dynamic_prot = 1; prop = (const __be32 *)of_get_flat_dt_prop(node, "reg", &len); if (!prop&&(depth != 2)) return 0; cma_name = (char *)of_get_flat_dt_prop(node, "hisi,cma-name", NULL); base = (phys_addr_t)dt_mem_next_cell(addr_cells, &prop); size = (phys_addr_t)dt_mem_next_cell(size_cells, &prop); pr_err("size is %lu base 0x%lu cma_name %s\n", (unsigned long)size / SZ_1M, (unsigned long)base, cma_name); __dma_contiguous_reserve_area(size, base, SZ_4M, cma_name, NULL,sec_prot,dynamic_prot); return 0; }
static int of_batterydata_read_lut(const struct device_node *np, int max_cols, int max_rows, int *ncols, int *nrows, int *col_legend_data, int *row_legend_data, int *lut_data) { struct property *prop; const __be32 *data; int cols, rows, size, i, j, *out_values; prop = of_find_property(np, "qcom,lut-col-legend", NULL); if (!prop) { pr_err("%s: No col legend found\n", np->name); return -EINVAL; } else if (!prop->value) { pr_err("%s: No col legend value found, np->name\n", np->name); return -ENODATA; } else if (prop->length > max_cols * sizeof(int)) { pr_err("%s: Too many columns\n", np->name); return -EINVAL; } cols = prop->length/sizeof(int); *ncols = cols; data = prop->value; for (i = 0; i < cols; i++) *col_legend_data++ = be32_to_cpup(data++); prop = of_find_property(np, "qcom,lut-row-legend", NULL); if (!prop || row_legend_data == NULL) { /* single row lut */ rows = 1; } else if (!prop->value) { pr_err("%s: No row legend value found\n", np->name); return -ENODATA; } else if (prop->length > max_rows * sizeof(int)) { pr_err("%s: Too many rows\n", np->name); return -EINVAL; } else { rows = prop->length/sizeof(int); *nrows = rows; data = prop->value; for (i = 0; i < rows; i++) *row_legend_data++ = be32_to_cpup(data++); } prop = of_find_property(np, "qcom,lut-data", NULL); if (!prop) { pr_err("prop 'qcom,lut-data' not found\n"); return -EINVAL; } data = prop->value; size = prop->length/sizeof(int); if (size != cols * rows) { pr_err("%s: data size mismatch, %dx%d != %d\n", np->name, cols, rows, size); return -EINVAL; } for (i = 0; i < rows; i++) { out_values = lut_data + (max_cols * i); for (j = 0; j < cols; j++) { *out_values++ = be32_to_cpup(data++); pr_debug("Value = %d\n", *(out_values-1)); } } return 0; }
static struct gpio_regulator_config * of_get_gpio_regulator_config(struct device *dev, struct device_node *np) { struct gpio_regulator_config *config; struct property *prop; const char *regtype; int proplen, gpio, i; int ret; config = devm_kzalloc(dev, sizeof(struct gpio_regulator_config), GFP_KERNEL); if (!config) return ERR_PTR(-ENOMEM); config->init_data = of_get_regulator_init_data(dev, np); if (!config->init_data) return ERR_PTR(-EINVAL); config->supply_name = config->init_data->constraints.name; if (of_property_read_bool(np, "enable-active-high")) config->enable_high = true; if (of_property_read_bool(np, "enable-at-boot")) config->enabled_at_boot = true; of_property_read_u32(np, "startup-delay-us", &config->startup_delay); config->enable_gpio = of_get_named_gpio(np, "enable-gpio", 0); /* Fetch GPIOs. */ config->nr_gpios = of_gpio_count(np); config->gpios = devm_kzalloc(dev, sizeof(struct gpio) * config->nr_gpios, GFP_KERNEL); if (!config->gpios) return ERR_PTR(-ENOMEM); prop = of_find_property(np, "gpios-states", NULL); if (prop) { proplen = prop->length / sizeof(int); if (proplen != config->nr_gpios) { /* gpios <-> gpios-states mismatch */ prop = NULL; } } for (i = 0; i < config->nr_gpios; i++) { gpio = of_get_named_gpio(np, "gpios", i); if (gpio < 0) break; config->gpios[i].gpio = gpio; if (prop && be32_to_cpup((int *)prop->value + i)) config->gpios[i].flags = GPIOF_OUT_INIT_HIGH; } /* Fetch states. */ prop = of_find_property(np, "states", NULL); if (!prop) { dev_err(dev, "No 'states' property found\n"); return ERR_PTR(-EINVAL); } proplen = prop->length / sizeof(int); config->states = devm_kzalloc(dev, sizeof(struct gpio_regulator_state) * (proplen / 2), GFP_KERNEL); if (!config->states) return ERR_PTR(-ENOMEM); for (i = 0; i < proplen / 2; i++) { config->states[i].value = be32_to_cpup((int *)prop->value + (i * 2)); config->states[i].gpios = be32_to_cpup((int *)prop->value + (i * 2 + 1)); } config->nr_states = i; config->type = REGULATOR_VOLTAGE; ret = of_property_read_string(np, "regulator-type", ®type); if (ret >= 0) { if (!strncmp("voltage", regtype, 7)) config->type = REGULATOR_VOLTAGE; else if (!strncmp("current", regtype, 7)) config->type = REGULATOR_CURRENT; else dev_warn(dev, "Unknown regulator-type '%s'\n", regtype); } return config; }
void of_register_spi_devices(struct spi_master *master, struct device_node *np) { struct spi_device *spi; struct device_node *nc; const __be32 *prop; int rc; int len; for_each_child_of_node(np, nc) { /* Alloc an spi_device */ spi = spi_alloc_device(master); if (!spi) { dev_err(&master->dev, "spi_device alloc error for %s\n", nc->full_name); spi_dev_put(spi); continue; } /* Select device driver */ if (of_modalias_node(nc, spi->modalias, sizeof(spi->modalias)) < 0) { dev_err(&master->dev, "cannot find modalias for %s\n", nc->full_name); spi_dev_put(spi); continue; } /* Device address */ prop = of_get_property(nc, "reg", &len); if (!prop || len < sizeof(*prop)) { dev_err(&master->dev, "%s has no 'reg' property\n", nc->full_name); spi_dev_put(spi); continue; } spi->chip_select = be32_to_cpup(prop); /* Mode (clock phase/polarity/etc.) */ if (of_find_property(nc, "spi-cpha", NULL)) spi->mode |= SPI_CPHA; if (of_find_property(nc, "spi-cpol", NULL)) spi->mode |= SPI_CPOL; if (of_find_property(nc, "spi-cs-high", NULL)) spi->mode |= SPI_CS_HIGH; /* Device speed */ prop = of_get_property(nc, "spi-max-frequency", &len); if (!prop || len < sizeof(*prop)) { dev_err(&master->dev, "%s has no 'spi-max-frequency' property\n", nc->full_name); spi_dev_put(spi); continue; } spi->max_speed_hz = be32_to_cpup(prop); /* IRQ */ spi->irq = irq_of_parse_and_map(nc, 0); /* Store a pointer to the node in the device structure */ of_node_get(nc); spi->dev.of_node = nc; /* Register the new device */ request_module(spi->modalias); rc = spi_add_device(spi); if (rc) { dev_err(&master->dev, "spi_device register error %s\n", nc->full_name); spi_dev_put(spi); } }
int of_irq_map_raw(struct device_node *parent, const __be32 *intspec, u32 ointsize, const __be32 *addr, struct of_irq *out_irq) { struct device_node *ipar, *tnode, *old = NULL, *newpar = NULL; const __be32 *tmp, *imap, *imask; u32 intsize = 1, addrsize, newintsize = 0, newaddrsize = 0; int imaplen, match, i; pr_debug("of_irq_map_raw: par=%s,intspec=[0x%08x 0x%08x...],ointsize=%d\n", parent->full_name, be32_to_cpup(intspec), be32_to_cpup(intspec + 1), ointsize); ipar = of_node_get(parent); /* */ do { tmp = of_get_property(ipar, "#interrupt-cells", NULL); if (tmp != NULL) { intsize = be32_to_cpu(*tmp); break; } tnode = ipar; ipar = of_irq_find_parent(ipar); of_node_put(tnode); } while (ipar); if (ipar == NULL) { pr_debug(" -> no parent found !\n"); goto fail; } pr_debug("of_irq_map_raw: ipar=%s, size=%d\n", ipar->full_name, intsize); if (ointsize != intsize) return -EINVAL; /* */ old = of_node_get(ipar); do { tmp = of_get_property(old, "#address-cells", NULL); tnode = of_get_parent(old); of_node_put(old); old = tnode; } while (old && tmp == NULL); of_node_put(old); old = NULL; addrsize = (tmp == NULL) ? 2 : be32_to_cpu(*tmp); pr_debug(" -> addrsize=%d\n", addrsize); /* */ while (ipar != NULL) { /* */ if (of_get_property(ipar, "interrupt-controller", NULL) != NULL) { pr_debug(" -> got it !\n"); for (i = 0; i < intsize; i++) out_irq->specifier[i] = of_read_number(intspec +i, 1); out_irq->size = intsize; out_irq->controller = ipar; of_node_put(old); return 0; } /* */ imap = of_get_property(ipar, "interrupt-map", &imaplen); /* */ if (imap == NULL) { pr_debug(" -> no map, getting parent\n"); newpar = of_irq_find_parent(ipar); goto skiplevel; } imaplen /= sizeof(u32); /* */ imask = of_get_property(ipar, "interrupt-map-mask", NULL); /* */ if (addr == NULL && addrsize != 0) { pr_debug(" -> no reg passed in when needed !\n"); goto fail; } /* */ match = 0; while (imaplen > (addrsize + intsize + 1) && !match) { /* */ match = 1; for (i = 0; i < addrsize && match; ++i) { u32 mask = imask ? imask[i] : 0xffffffffu; match = ((addr[i] ^ imap[i]) & mask) == 0; } for (; i < (addrsize + intsize) && match; ++i) { u32 mask = imask ? imask[i] : 0xffffffffu; match = ((intspec[i-addrsize] ^ imap[i]) & mask) == 0; } imap += addrsize + intsize; imaplen -= addrsize + intsize; pr_debug(" -> match=%d (imaplen=%d)\n", match, imaplen); /* */ if (of_irq_workarounds & OF_IMAP_NO_PHANDLE) newpar = of_node_get(of_irq_dflt_pic); else newpar = of_find_node_by_phandle(be32_to_cpup(imap)); imap++; --imaplen; /* */ if (newpar == NULL) { pr_debug(" -> imap parent not found !\n"); goto fail; } /* */ tmp = of_get_property(newpar, "#interrupt-cells", NULL); if (tmp == NULL) { pr_debug(" -> parent lacks #interrupt-cells!\n"); goto fail; } newintsize = be32_to_cpu(*tmp); tmp = of_get_property(newpar, "#address-cells", NULL); newaddrsize = (tmp == NULL) ? 0 : be32_to_cpu(*tmp); pr_debug(" -> newintsize=%d, newaddrsize=%d\n", newintsize, newaddrsize); /* */ if (imaplen < (newaddrsize + newintsize)) goto fail; imap += newaddrsize + newintsize; imaplen -= newaddrsize + newintsize; pr_debug(" -> imaplen=%d\n", imaplen); } if (!match) goto fail; of_node_put(old); old = of_node_get(newpar); addrsize = newaddrsize; intsize = newintsize; intspec = imap - intsize; addr = intspec - addrsize; skiplevel: /* */ pr_debug(" -> new parent: %s\n", newpar ? newpar->full_name : "<>"); of_node_put(ipar); ipar = newpar; newpar = NULL; } fail: of_node_put(ipar); of_node_put(old); of_node_put(newpar); return -EINVAL; }
/** * unflatten_dt_node - Alloc and populate a device_node from the flat tree * @blob: The parent device tree blob * @mem: Memory chunk to use for allocating device nodes and properties * @p: pointer to node in flat tree * @dad: Parent struct device_node * @allnextpp: pointer to ->allnext from last allocated device_node * @fpsize: Size of the node path up at the current depth. */ static unsigned long unflatten_dt_node(struct boot_param_header *blob, unsigned long mem, unsigned long *p, struct device_node *dad, struct device_node ***allnextpp, unsigned long fpsize) { struct device_node *np; struct property *pp, **prev_pp = NULL; char *pathp; u32 tag; unsigned int l, allocl; int has_name = 0; int new_format = 0; tag = be32_to_cpup((__be32 *)(*p)); if (tag != OF_DT_BEGIN_NODE) { pr_err("Weird tag at start of node: %x\n", tag); return mem; } *p += 4; pathp = (char *)*p; l = allocl = strlen(pathp) + 1; *p = ALIGN(*p + l, 4); /* version 0x10 has a more compact unit name here instead of the full * path. we accumulate the full path size using "fpsize", we'll rebuild * it later. We detect this because the first character of the name is * not '/'. */ if ((*pathp) != '/') { new_format = 1; if (fpsize == 0) { /* root node: special case. fpsize accounts for path * plus terminating zero. root node only has '/', so * fpsize should be 2, but we want to avoid the first * level nodes to have two '/' so we use fpsize 1 here */ fpsize = 1; allocl = 2; } else { /* account for '/' and path size minus terminal 0 * already in 'l' */ fpsize += l; allocl = fpsize; } } np = unflatten_dt_alloc(&mem, sizeof(struct device_node) + allocl, __alignof__(struct device_node)); if (allnextpp) { memset(np, 0, sizeof(*np)); np->full_name = ((char *)np) + sizeof(struct device_node); if (new_format) { char *fn = np->full_name; /* rebuild full path for new format */ if (dad && dad->parent) { strcpy(fn, dad->full_name); #ifdef DEBUG if ((strlen(fn) + l + 1) != allocl) { pr_debug("%s: p: %d, l: %d, a: %d\n", pathp, (int)strlen(fn), l, allocl); } #endif fn += strlen(fn); } *(fn++) = '/'; memcpy(fn, pathp, l); } else memcpy(np->full_name, pathp, l); prev_pp = &np->properties; **allnextpp = np; *allnextpp = &np->allnext; if (dad != NULL) { np->parent = dad; /* we temporarily use the next field as `last_child'*/ if (dad->next == NULL) dad->child = np; else dad->next->sibling = np; dad->next = np; } kref_init(&np->kref); } /* process properties */ while (1) { u32 sz, noff; char *pname; tag = be32_to_cpup((__be32 *)(*p)); if (tag == OF_DT_NOP) { *p += 4; continue; } if (tag != OF_DT_PROP) break; *p += 4; sz = be32_to_cpup((__be32 *)(*p)); noff = be32_to_cpup((__be32 *)((*p) + 4)); *p += 8; if (be32_to_cpu(blob->version) < 0x10) *p = ALIGN(*p, sz >= 8 ? 8 : 4); pname = of_fdt_get_string(blob, noff); if (pname == NULL) { pr_info("Can't find property name in list !\n"); break; } if (strcmp(pname, "name") == 0) has_name = 1; l = strlen(pname) + 1; pp = unflatten_dt_alloc(&mem, sizeof(struct property), __alignof__(struct property)); if (allnextpp) { /* We accept flattened tree phandles either in * ePAPR-style "phandle" properties, or the * legacy "linux,phandle" properties. If both * appear and have different values, things * will get weird. Don't do that. */ if ((strcmp(pname, "phandle") == 0) || (strcmp(pname, "linux,phandle") == 0)) { if (np->phandle == 0) np->phandle = be32_to_cpup((__be32*)*p); } /* And we process the "ibm,phandle" property * used in pSeries dynamic device tree * stuff */ if (strcmp(pname, "ibm,phandle") == 0) np->phandle = be32_to_cpup((__be32 *)*p); pp->name = pname; pp->length = sz; pp->value = (void *)*p; *prev_pp = pp; prev_pp = &pp->next; } *p = ALIGN((*p) + sz, 4); } /* with version 0x10 we may not have the name property, recreate * it here from the unit name if absent */ if (!has_name) { char *p1 = pathp, *ps = pathp, *pa = NULL; int sz; while (*p1) { if ((*p1) == '@') pa = p1; if ((*p1) == '/') ps = p1 + 1; p1++; } if (pa < ps) pa = p1; sz = (pa - ps) + 1; pp = unflatten_dt_alloc(&mem, sizeof(struct property) + sz, __alignof__(struct property)); if (allnextpp) { pp->name = "name"; pp->length = sz; pp->value = pp + 1; *prev_pp = pp; prev_pp = &pp->next; memcpy(pp->value, ps, sz - 1); ((char *)pp->value)[sz - 1] = 0; pr_debug("fixed up name for %s -> %s\n", pathp, (char *)pp->value); } }
static int fsl_esai_probe(struct platform_device *pdev) { struct device_node *np = pdev->dev.of_node; struct fsl_esai *esai_priv; struct resource *res; const uint32_t *iprop; void __iomem *regs; int irq, ret; esai_priv = devm_kzalloc(&pdev->dev, sizeof(*esai_priv), GFP_KERNEL); if (!esai_priv) return -ENOMEM; esai_priv->pdev = pdev; strcpy(esai_priv->name, np->name); /* Get the addresses and IRQ */ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); regs = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR(regs)) return PTR_ERR(regs); esai_priv->regmap = devm_regmap_init_mmio_clk(&pdev->dev, "core", regs, &fsl_esai_regmap_config); if (IS_ERR(esai_priv->regmap)) { dev_err(&pdev->dev, "failed to init regmap: %ld\n", PTR_ERR(esai_priv->regmap)); return PTR_ERR(esai_priv->regmap); } esai_priv->coreclk = devm_clk_get(&pdev->dev, "core"); if (IS_ERR(esai_priv->coreclk)) { dev_err(&pdev->dev, "failed to get core clock: %ld\n", PTR_ERR(esai_priv->coreclk)); return PTR_ERR(esai_priv->coreclk); } esai_priv->extalclk = devm_clk_get(&pdev->dev, "extal"); if (IS_ERR(esai_priv->extalclk)) dev_warn(&pdev->dev, "failed to get extal clock: %ld\n", PTR_ERR(esai_priv->extalclk)); esai_priv->fsysclk = devm_clk_get(&pdev->dev, "fsys"); if (IS_ERR(esai_priv->fsysclk)) dev_warn(&pdev->dev, "failed to get fsys clock: %ld\n", PTR_ERR(esai_priv->fsysclk)); irq = platform_get_irq(pdev, 0); if (irq < 0) { dev_err(&pdev->dev, "no irq for node %s\n", np->full_name); return irq; } ret = devm_request_irq(&pdev->dev, irq, esai_isr, 0, esai_priv->name, esai_priv); if (ret) { dev_err(&pdev->dev, "failed to claim irq %u\n", irq); return ret; } /* Set a default slot size */ esai_priv->slot_width = 32; /* Set a default master/slave state */ esai_priv->slave_mode = true; /* Determine the FIFO depth */ iprop = of_get_property(np, "fsl,fifo-depth", NULL); if (iprop) esai_priv->fifo_depth = be32_to_cpup(iprop); else esai_priv->fifo_depth = 64; esai_priv->dma_params_tx.maxburst = 16; esai_priv->dma_params_rx.maxburst = 16; esai_priv->dma_params_tx.addr = res->start + REG_ESAI_ETDR; esai_priv->dma_params_rx.addr = res->start + REG_ESAI_ERDR; esai_priv->synchronous = of_property_read_bool(np, "fsl,esai-synchronous"); /* Implement full symmetry for synchronous mode */ if (esai_priv->synchronous) { fsl_esai_dai.symmetric_rates = 1; fsl_esai_dai.symmetric_channels = 1; fsl_esai_dai.symmetric_samplebits = 1; } dev_set_drvdata(&pdev->dev, esai_priv); /* Reset ESAI unit */ ret = regmap_write(esai_priv->regmap, REG_ESAI_ECR, ESAI_ECR_ERST); if (ret) { dev_err(&pdev->dev, "failed to reset ESAI: %d\n", ret); return ret; } /* * We need to enable ESAI so as to access some of its registers. * Otherwise, we would fail to dump regmap from user space. */ ret = regmap_write(esai_priv->regmap, REG_ESAI_ECR, ESAI_ECR_ESAIEN); if (ret) { dev_err(&pdev->dev, "failed to enable ESAI: %d\n", ret); return ret; } ret = devm_snd_soc_register_component(&pdev->dev, &fsl_esai_component, &fsl_esai_dai, 1); if (ret) { dev_err(&pdev->dev, "failed to register DAI: %d\n", ret); return ret; } ret = imx_pcm_dma_init(pdev); if (ret) dev_err(&pdev->dev, "failed to init imx pcm dma: %d\n", ret); return ret; }
static int tpiu_parse_of_data(struct platform_device *pdev, struct tpiu_drvdata *drvdata) { struct device_node *node = pdev->dev.of_node; struct device_node *reg_node = NULL; struct device *dev = &pdev->dev; const __be32 *prop; int i, len, gpio, ret; uint32_t *seta_cfgs, *setb_cfgs; struct pinctrl *pctrl; reg_node = of_parse_phandle(node, "vdd-supply", 0); if (reg_node) { drvdata->reg = devm_regulator_get(dev, "vdd"); if (IS_ERR(drvdata->reg)) return PTR_ERR(drvdata->reg); prop = of_get_property(node, "qcom,vdd-voltage-level", &len); if (!prop || (len != (2 * sizeof(__be32)))) { dev_err(dev, "sdc voltage levels not specified\n"); } else { drvdata->reg_low = be32_to_cpup(&prop[0]); drvdata->reg_high = be32_to_cpup(&prop[1]); } prop = of_get_property(node, "qcom,vdd-current-level", &len); if (!prop || (len != (2 * sizeof(__be32)))) { dev_err(dev, "sdc current levels not specified\n"); } else { drvdata->reg_lpm = be32_to_cpup(&prop[0]); drvdata->reg_hpm = be32_to_cpup(&prop[1]); } of_node_put(reg_node); } else { dev_err(dev, "sdc voltage supply not specified or available\n"); } reg_node = of_parse_phandle(node, "vdd-io-supply", 0); if (reg_node) { drvdata->reg_io = devm_regulator_get(dev, "vdd-io"); if (IS_ERR(drvdata->reg_io)) return PTR_ERR(drvdata->reg_io); prop = of_get_property(node, "qcom,vdd-io-voltage-level", &len); if (!prop || (len != (2 * sizeof(__be32)))) { dev_err(dev, "sdc io voltage levels not specified\n"); } else { drvdata->reg_low_io = be32_to_cpup(&prop[0]); drvdata->reg_high_io = be32_to_cpup(&prop[1]); } prop = of_get_property(node, "qcom,vdd-io-current-level", &len); if (!prop || (len != (2 * sizeof(__be32)))) { dev_err(dev, "sdc io current levels not specified\n"); } else { drvdata->reg_lpm_io = be32_to_cpup(&prop[0]); drvdata->reg_hpm_io = be32_to_cpup(&prop[1]); } of_node_put(reg_node); } else { dev_err(dev, "sdc io voltage supply not specified or available\n"); } drvdata->out_mode = TPIU_OUT_MODE_MICTOR; drvdata->set = TPIU_SET_B; pctrl = devm_pinctrl_get(dev); if (!IS_ERR(pctrl)) { drvdata->tpiu_pctrl = devm_kzalloc(dev, sizeof(struct tpiu_pinctrl), GFP_KERNEL); if (!drvdata->tpiu_pctrl) return -ENOMEM; devm_pinctrl_put(pctrl); goto out; } dev_err(dev, "Pinctrl failed, falling back to GPIO lib\n"); drvdata->seta_gpiocnt = of_gpio_named_count(node, "qcom,seta-gpios"); if (drvdata->seta_gpiocnt > 0) { drvdata->seta_gpios = devm_kzalloc(dev, sizeof(*drvdata->seta_gpios) * drvdata->seta_gpiocnt, GFP_KERNEL); if (!drvdata->seta_gpios) return -ENOMEM; for (i = 0; i < drvdata->seta_gpiocnt; i++) { gpio = of_get_named_gpio(node, "qcom,seta-gpios", i); if (!gpio_is_valid(gpio)) return gpio; drvdata->seta_gpios[i] = gpio; } drvdata->seta_cfgs = devm_kzalloc(dev, sizeof(*drvdata->seta_cfgs) * drvdata->seta_gpiocnt, GFP_KERNEL); if (!drvdata->seta_cfgs) return -ENOMEM; seta_cfgs = devm_kzalloc(dev, sizeof(*seta_cfgs) * drvdata->seta_gpiocnt, GFP_KERNEL); if (!seta_cfgs) return -ENOMEM; ret = of_property_read_u32_array(node, "qcom,seta-gpios-func", (u32 *)seta_cfgs, drvdata->seta_gpiocnt); if (ret) return ret; for (i = 0; i < drvdata->seta_gpiocnt; i++) drvdata->seta_cfgs[i].func = seta_cfgs[i]; ret = of_property_read_u32_array(node, "qcom,seta-gpios-drv", (u32 *)seta_cfgs, drvdata->seta_gpiocnt); if (ret) return ret; for (i = 0; i < drvdata->seta_gpiocnt; i++) drvdata->seta_cfgs[i].drv = seta_cfgs[i]; ret = of_property_read_u32_array(node, "qcom,seta-gpios-pull", (u32 *)seta_cfgs, drvdata->seta_gpiocnt); if (ret) return ret; for (i = 0; i < drvdata->seta_gpiocnt; i++) drvdata->seta_cfgs[i].pull = seta_cfgs[i]; ret = of_property_read_u32_array(node, "qcom,seta-gpios-dir", (u32 *)seta_cfgs, drvdata->seta_gpiocnt); if (ret) return ret; for (i = 0; i < drvdata->seta_gpiocnt; i++) drvdata->seta_cfgs[i].dir = seta_cfgs[i]; devm_kfree(dev, seta_cfgs); } else { dev_err(dev, "seta gpios not specified\n"); } drvdata->setb_gpiocnt = of_gpio_named_count(node, "qcom,setb-gpios"); if (drvdata->setb_gpiocnt > 0) { drvdata->setb_gpios = devm_kzalloc(dev, sizeof(*drvdata->setb_gpios) * drvdata->setb_gpiocnt, GFP_KERNEL); if (!drvdata->setb_gpios) return -ENOMEM; for (i = 0; i < drvdata->setb_gpiocnt; i++) { gpio = of_get_named_gpio(node, "qcom,setb-gpios", i); if (!gpio_is_valid(gpio)) return gpio; drvdata->setb_gpios[i] = gpio; } drvdata->setb_cfgs = devm_kzalloc(dev, sizeof(*drvdata->setb_cfgs) * drvdata->setb_gpiocnt, GFP_KERNEL); if (!drvdata->setb_cfgs) return -ENOMEM; setb_cfgs = devm_kzalloc(dev, sizeof(*setb_cfgs) * drvdata->setb_gpiocnt, GFP_KERNEL); if (!setb_cfgs) return -ENOMEM; ret = of_property_read_u32_array(node, "qcom,setb-gpios-func", (u32 *)setb_cfgs, drvdata->setb_gpiocnt); if (ret) return ret; for (i = 0; i < drvdata->setb_gpiocnt; i++) drvdata->setb_cfgs[i].func = setb_cfgs[i]; ret = of_property_read_u32_array(node, "qcom,setb-gpios-drv", (u32 *)setb_cfgs, drvdata->setb_gpiocnt); if (ret) return ret; for (i = 0; i < drvdata->setb_gpiocnt; i++) drvdata->setb_cfgs[i].drv = setb_cfgs[i]; ret = of_property_read_u32_array(node, "qcom,setb-gpios-pull", (u32 *)setb_cfgs, drvdata->setb_gpiocnt); if (ret) return ret; for (i = 0; i < drvdata->setb_gpiocnt; i++) drvdata->setb_cfgs[i].pull = setb_cfgs[i]; ret = of_property_read_u32_array(node, "qcom,setb-gpios-dir", (u32 *)setb_cfgs, drvdata->setb_gpiocnt); if (ret) return ret; for (i = 0; i < drvdata->setb_gpiocnt; i++) drvdata->setb_cfgs[i].dir = setb_cfgs[i]; devm_kfree(dev, setb_cfgs); } else { dev_err(dev, "setb gpios not specified\n"); } out: drvdata->nidnt = of_property_read_bool(pdev->dev.of_node, "qcom,nidnt"); return 0; }
/** * of_irq_parse_one - Resolve an interrupt for a device * @device: the device whose interrupt is to be resolved * @index: index of the interrupt to resolve * @out_irq: structure of_irq filled by this function * * This function resolves an interrupt for a node by walking the interrupt tree, * finding which interrupt controller node it is attached to, and returning the * interrupt specifier that can be used to retrieve a Linux IRQ number. */ int of_irq_parse_one(struct device_node *device, int index, struct of_phandle_args *out_irq) { struct device_node *p; const __be32 *intspec, *tmp, *addr; u32 intsize, intlen; int i, res; pr_debug("of_irq_parse_one: dev=%s, index=%d\n", of_node_full_name(device), index); /* OldWorld mac stuff is "special", handle out of line */ if (of_irq_workarounds & OF_IMAP_OLDWORLD_MAC) return of_irq_parse_oldworld(device, index, out_irq); /* Get the reg property (if any) */ addr = of_get_property(device, "reg", NULL); /* Try the new-style interrupts-extended first */ res = of_parse_phandle_with_args(device, "interrupts-extended", "#interrupt-cells", index, out_irq); if (!res) return of_irq_parse_raw(addr, out_irq); /* Get the interrupts property */ intspec = of_get_property(device, "interrupts", &intlen); if (intspec == NULL) return -EINVAL; intlen /= sizeof(*intspec); pr_debug(" intspec=%d intlen=%d\n", be32_to_cpup(intspec), intlen); /* Look for the interrupt parent. */ p = of_irq_find_parent(device); if (p == NULL) return -EINVAL; /* Get size of interrupt specifier */ tmp = of_get_property(p, "#interrupt-cells", NULL); if (tmp == NULL) { res = -EINVAL; goto out; } intsize = be32_to_cpu(*tmp); pr_debug(" intsize=%d intlen=%d\n", intsize, intlen); /* Check index */ if ((index + 1) * intsize > intlen) { res = -EINVAL; goto out; } /* Copy intspec into irq structure */ intspec += index * intsize; out_irq->np = p; out_irq->args_count = intsize; for (i = 0; i < intsize; i++) out_irq->args[i] = be32_to_cpup(intspec++); /* Check if there are any interrupt-map translations to process */ res = of_irq_parse_raw(addr, out_irq); out: of_node_put(p); return res; }
int fdtdec_parse_phandle_with_args(const void *blob, int src_node, const char *list_name, const char *cells_name, int cell_count, int index, struct fdtdec_phandle_args *out_args) { const __be32 *list, *list_end; int rc = 0, size, cur_index = 0; uint32_t count = 0; int node = -1; int phandle; /* Retrieve the phandle list property */ list = fdt_getprop(blob, src_node, list_name, &size); if (!list) return -ENOENT; list_end = list + size / sizeof(*list); /* Loop over the phandles until all the requested entry is found */ while (list < list_end) { rc = -EINVAL; count = 0; /* * If phandle is 0, then it is an empty entry with no * arguments. Skip forward to the next entry. */ phandle = be32_to_cpup(list++); if (phandle) { /* * Find the provider node and parse the #*-cells * property to determine the argument length. * * This is not needed if the cell count is hard-coded * (i.e. cells_name not set, but cell_count is set), * except when we're going to return the found node * below. */ if (cells_name || cur_index == index) { node = fdt_node_offset_by_phandle(blob, phandle); if (!node) { debug("%s: could not find phandle\n", fdt_get_name(blob, src_node, NULL)); goto err; } } if (cells_name) { count = fdtdec_get_int(blob, node, cells_name, -1); if (count == -1) { debug("%s: could not get %s for %s\n", fdt_get_name(blob, src_node, NULL), cells_name, fdt_get_name(blob, node, NULL)); goto err; } } else { count = cell_count; } /* * Make sure that the arguments actually fit in the * remaining property data length */ if (list + count > list_end) { debug("%s: arguments longer than property\n", fdt_get_name(blob, src_node, NULL)); goto err; } } /* * All of the error cases above bail out of the loop, so at * this point, the parsing is successful. If the requested * index matches, then fill the out_args structure and return, * or return -ENOENT for an empty entry. */ rc = -ENOENT; if (cur_index == index) { if (!phandle) goto err; if (out_args) { int i; if (count > MAX_PHANDLE_ARGS) { debug("%s: too many arguments %d\n", fdt_get_name(blob, src_node, NULL), count); count = MAX_PHANDLE_ARGS; } out_args->node = node; out_args->args_count = count; for (i = 0; i < count; i++) { out_args->args[i] = be32_to_cpup(list++); } } /* Found it! return success */ return 0; } node = -1; list += count; cur_index++; } /* * Result will be one of: * -ENOENT : index is for empty phandle * -EINVAL : parsing error on data * [1..n] : Number of phandle (count mode; when index = -1) */ rc = index < 0 ? cur_index : -ENOENT; err: return rc; }
int of_mdiobus_register(struct mii_bus *mdio, struct device_node *np) { struct phy_device *phy; struct device_node *child; int rc, i; mdio->phy_mask = ~0; if (mdio->irq) for (i=0; i<PHY_MAX_ADDR; i++) mdio->irq[i] = PHY_POLL; rc = mdiobus_register(mdio); if (rc) return rc; for_each_child_of_node(np, child) { const __be32 *paddr; u32 addr; int len; paddr = of_get_property(child, "reg", &len); if (!paddr || len < sizeof(*paddr)) { dev_err(&mdio->dev, "%s has invalid PHY address\n", child->full_name); continue; } addr = be32_to_cpup(paddr); if (addr >= 32) { dev_err(&mdio->dev, "%s PHY address %i is too large\n", child->full_name, addr); continue; } if (mdio->irq) { mdio->irq[addr] = irq_of_parse_and_map(child, 0); if (!mdio->irq[addr]) mdio->irq[addr] = PHY_POLL; } phy = get_phy_device(mdio, addr); if (!phy || IS_ERR(phy)) { dev_err(&mdio->dev, "error probing PHY at address %i\n", addr); continue; } of_node_get(child); phy->dev.of_node = child; rc = phy_device_register(phy); if (rc) { phy_device_free(phy); of_node_put(child); continue; } dev_dbg(&mdio->dev, "registered phy %s at address %i\n", child->name, addr); } return 0; }
static int ide_floppy_get_capacity(ide_drive_t *drive) { struct ide_disk_obj *floppy = drive->driver_data; struct gendisk *disk = floppy->disk; struct ide_atapi_pc pc; u8 *cap_desc; u8 pc_buf[256], header_len, desc_cnt; int i, rc = 1, blocks, length; ide_debug_log(IDE_DBG_FUNC, "enter"); drive->bios_cyl = 0; drive->bios_head = drive->bios_sect = 0; floppy->blocks = 0; floppy->bs_factor = 1; drive->capacity64 = 0; ide_floppy_create_read_capacity_cmd(&pc); if (ide_queue_pc_tail(drive, disk, &pc, pc_buf, pc.req_xfer)) { printk(KERN_ERR PFX "Can't get floppy parameters\n"); return 1; } header_len = pc_buf[3]; cap_desc = &pc_buf[4]; desc_cnt = header_len / 8; for (i = 0; i < desc_cnt; i++) { unsigned int desc_start = 4 + i*8; blocks = be32_to_cpup((__be32 *)&pc_buf[desc_start]); length = be16_to_cpup((__be16 *)&pc_buf[desc_start + 6]); ide_debug_log(IDE_DBG_PROBE, "Descriptor %d: %dkB, %d blocks, " "%d sector size", i, blocks * length / 1024, blocks, length); if (i) continue; switch (pc_buf[desc_start + 4] & 0x03) { case CAPACITY_UNFORMATTED: if (!(drive->atapi_flags & IDE_AFLAG_CLIK_DRIVE)) break; case CAPACITY_CURRENT: if (memcmp(cap_desc, &floppy->cap_desc, 8)) printk(KERN_INFO PFX "%s: %dkB, %d blocks, %d " "sector size\n", drive->name, blocks * length / 1024, blocks, length); memcpy(&floppy->cap_desc, cap_desc, 8); if (!length || length % 512) { printk(KERN_NOTICE PFX "%s: %d bytes block size" " not supported\n", drive->name, length); } else { floppy->blocks = blocks; floppy->block_size = length; floppy->bs_factor = length / 512; if (floppy->bs_factor != 1) printk(KERN_NOTICE PFX "%s: Warning: " "non 512 bytes block size not " "fully supported\n", drive->name); drive->capacity64 = floppy->blocks * floppy->bs_factor; rc = 0; } break; case CAPACITY_NO_CARTRIDGE: printk(KERN_ERR PFX "%s: No disk in drive\n", drive->name); break; case CAPACITY_INVALID: printk(KERN_ERR PFX "%s: Invalid capacity for disk " "in drive\n", drive->name); break; } ide_debug_log(IDE_DBG_PROBE, "Descriptor 0 Code: %d", pc_buf[desc_start + 4] & 0x03); } if (!(drive->atapi_flags & IDE_AFLAG_CLIK_DRIVE)) (void) ide_floppy_get_flexible_disk_page(drive, &pc); return rc; }
int ni_mc_load_microcode(struct radeon_device *rdev) { const __be32 *fw_data; u32 mem_type, running, blackout = 0; u32 *io_mc_regs; int i, ucode_size, regs_size; if (!rdev->mc_fw) return -EINVAL; switch (rdev->family) { case CHIP_BARTS: io_mc_regs = (u32 *)&barts_io_mc_regs; ucode_size = BTC_MC_UCODE_SIZE; regs_size = BTC_IO_MC_REGS_SIZE; break; case CHIP_TURKS: io_mc_regs = (u32 *)&turks_io_mc_regs; ucode_size = BTC_MC_UCODE_SIZE; regs_size = BTC_IO_MC_REGS_SIZE; break; case CHIP_CAICOS: default: io_mc_regs = (u32 *)&caicos_io_mc_regs; ucode_size = BTC_MC_UCODE_SIZE; regs_size = BTC_IO_MC_REGS_SIZE; break; case CHIP_CAYMAN: io_mc_regs = (u32 *)&cayman_io_mc_regs; ucode_size = CAYMAN_MC_UCODE_SIZE; regs_size = BTC_IO_MC_REGS_SIZE; break; } mem_type = (RREG32(MC_SEQ_MISC0) & MC_SEQ_MISC0_GDDR5_MASK) >> MC_SEQ_MISC0_GDDR5_SHIFT; running = RREG32(MC_SEQ_SUP_CNTL) & RUN_MASK; if ((mem_type == MC_SEQ_MISC0_GDDR5_VALUE) && (running == 0)) { if (running) { blackout = RREG32(MC_SHARED_BLACKOUT_CNTL); WREG32(MC_SHARED_BLACKOUT_CNTL, 1); } /* reset the engine and set to writable */ WREG32(MC_SEQ_SUP_CNTL, 0x00000008); WREG32(MC_SEQ_SUP_CNTL, 0x00000010); /* load mc io regs */ for (i = 0; i < regs_size; i++) { WREG32(MC_SEQ_IO_DEBUG_INDEX, io_mc_regs[(i << 1)]); WREG32(MC_SEQ_IO_DEBUG_DATA, io_mc_regs[(i << 1) + 1]); } /* load the MC ucode */ fw_data = (const __be32 *)rdev->mc_fw->data; for (i = 0; i < ucode_size; i++) WREG32(MC_SEQ_SUP_PGM, be32_to_cpup(fw_data++)); /* put the engine back into the active state */ WREG32(MC_SEQ_SUP_CNTL, 0x00000008); WREG32(MC_SEQ_SUP_CNTL, 0x00000004); WREG32(MC_SEQ_SUP_CNTL, 0x00000001); /* wait for training to complete */ for (i = 0; i < rdev->usec_timeout; i++) { if (RREG32(MC_IO_PAD_CNTL_D0) & MEM_FALL_OUT_CMD) break; udelay(1); } if (running) WREG32(MC_SHARED_BLACKOUT_CNTL, blackout); } return 0; }
/** * unflatten_dt_node - Alloc and populate a device_node from the flat tree * @blob: The parent device tree blob * @mem: Memory chunk to use for allocating device nodes and properties * @p: pointer to node in flat tree * @dad: Parent struct device_node * @allnextpp: pointer to ->allnext from last allocated device_node * @fpsize: Size of the node path up at the current depth. */ static void * unflatten_dt_node(void *blob, void *mem, int *poffset, struct device_node *dad, struct device_node ***allnextpp, unsigned long fpsize) { const __be32 *p; struct device_node *np; struct property *pp, **prev_pp = NULL; const char *pathp; unsigned int l, allocl; static int depth = 0; int old_depth; int offset; int has_name = 0; int new_format = 0; pathp = fdt_get_name(blob, *poffset, &l); if (!pathp) return mem; allocl = l++; /* version 0x10 has a more compact unit name here instead of the full * path. we accumulate the full path size using "fpsize", we'll rebuild * it later. We detect this because the first character of the name is * not '/'. */ if ((*pathp) != '/') { new_format = 1; if (fpsize == 0) { /* root node: special case. fpsize accounts for path * plus terminating zero. root node only has '/', so * fpsize should be 2, but we want to avoid the first * level nodes to have two '/' so we use fpsize 1 here */ fpsize = 1; allocl = 2; l = 1; pathp = ""; } else { /* account for '/' and path size minus terminal 0 * already in 'l' */ fpsize += l; allocl = fpsize; } } np = unflatten_dt_alloc(&mem, sizeof(struct device_node) + allocl, __alignof__(struct device_node)); if (allnextpp) { char *fn; of_node_init(np); np->full_name = fn = ((char *)np) + sizeof(*np); if (new_format) { /* rebuild full path for new format */ if (dad && dad->parent) { strcpy(fn, dad->full_name); #ifdef DEBUG if ((strlen(fn) + l + 1) != allocl) { pr_debug("%s: p: %d, l: %d, a: %d\n", pathp, (int)strlen(fn), l, allocl); } #endif fn += strlen(fn); } *(fn++) = '/'; } memcpy(fn, pathp, l); prev_pp = &np->properties; **allnextpp = np; *allnextpp = &np->allnext; if (dad != NULL) { np->parent = dad; /* we temporarily use the next field as `last_child'*/ if (dad->next == NULL) dad->child = np; else dad->next->sibling = np; dad->next = np; } } /* process properties */ for (offset = fdt_first_property_offset(blob, *poffset); (offset >= 0); (offset = fdt_next_property_offset(blob, offset))) { const char *pname; u32 sz; if (!(p = fdt_getprop_by_offset(blob, offset, &pname, &sz))) { offset = -FDT_ERR_INTERNAL; break; } if (pname == NULL) { pr_info("Can't find property name in list !\n"); break; } if (strcmp(pname, "name") == 0) has_name = 1; pp = unflatten_dt_alloc(&mem, sizeof(struct property), __alignof__(struct property)); if (allnextpp) { /* We accept flattened tree phandles either in * ePAPR-style "phandle" properties, or the * legacy "linux,phandle" properties. If both * appear and have different values, things * will get weird. Don't do that. */ if ((strcmp(pname, "phandle") == 0) || (strcmp(pname, "linux,phandle") == 0)) { if (np->phandle == 0) np->phandle = be32_to_cpup(p); } /* And we process the "ibm,phandle" property * used in pSeries dynamic device tree * stuff */ if (strcmp(pname, "ibm,phandle") == 0) np->phandle = be32_to_cpup(p); pp->name = (char *)pname; pp->length = sz; pp->value = (__be32 *)p; *prev_pp = pp; prev_pp = &pp->next; } } /* with version 0x10 we may not have the name property, recreate * it here from the unit name if absent */ if (!has_name) { const char *p1 = pathp, *ps = pathp, *pa = NULL; int sz; while (*p1) { if ((*p1) == '@') pa = p1; if ((*p1) == '/') ps = p1 + 1; p1++; } if (pa < ps) pa = p1; sz = (pa - ps) + 1; pp = unflatten_dt_alloc(&mem, sizeof(struct property) + sz, __alignof__(struct property)); if (allnextpp) { pp->name = "name"; pp->length = sz; pp->value = pp + 1; *prev_pp = pp; prev_pp = &pp->next; memcpy(pp->value, ps, sz - 1); ((char *)pp->value)[sz - 1] = 0; pr_debug("fixed up name for %s -> %s\n", pathp, (char *)pp->value); } } if (allnextpp) { *prev_pp = NULL; np->name = of_get_property(np, "name", NULL); np->type = of_get_property(np, "device_type", NULL); if (!np->name) np->name = "<NULL>"; if (!np->type) np->type = "<NULL>"; } old_depth = depth; *poffset = fdt_next_node(blob, *poffset, &depth); if (depth < 0) depth = 0; while (*poffset > 0 && depth > old_depth) mem = unflatten_dt_node(blob, mem, poffset, np, allnextpp, fpsize); if (*poffset < 0 && *poffset != -FDT_ERR_NOTFOUND) pr_err("unflatten: error %d processing FDT\n", *poffset); return mem; }
static int mdio_mux_mmioreg_probe(struct platform_device *pdev) { struct device_node *np2, *np = pdev->dev.of_node; struct mdio_mux_mmioreg_state *s; struct resource res; const __be32 *iprop; int len, ret; dev_dbg(&pdev->dev, "probing node %pOF\n", np); s = devm_kzalloc(&pdev->dev, sizeof(*s), GFP_KERNEL); if (!s) return -ENOMEM; ret = of_address_to_resource(np, 0, &res); if (ret) { dev_err(&pdev->dev, "could not obtain memory map for node %pOF\n", np); return ret; } s->phys = res.start; s->iosize = resource_size(&res); if (s->iosize != sizeof(uint8_t) && s->iosize != sizeof(uint16_t) && s->iosize != sizeof(uint32_t)) { dev_err(&pdev->dev, "only 8/16/32-bit registers are supported\n"); return -EINVAL; } iprop = of_get_property(np, "mux-mask", &len); if (!iprop || len != sizeof(uint32_t)) { dev_err(&pdev->dev, "missing or invalid mux-mask property\n"); return -ENODEV; } if (be32_to_cpup(iprop) >= BIT(s->iosize * 8)) { dev_err(&pdev->dev, "only 8/16/32-bit registers are supported\n"); return -EINVAL; } s->mask = be32_to_cpup(iprop); /* * Verify that the 'reg' property of each child MDIO bus does not * set any bits outside of the 'mask'. */ for_each_available_child_of_node(np, np2) { iprop = of_get_property(np2, "reg", &len); if (!iprop || len != sizeof(uint32_t)) { dev_err(&pdev->dev, "mdio-mux child node %pOF is " "missing a 'reg' property\n", np2); of_node_put(np2); return -ENODEV; } if (be32_to_cpup(iprop) & ~s->mask) { dev_err(&pdev->dev, "mdio-mux child node %pOF has " "a 'reg' value with unmasked bits\n", np2); of_node_put(np2); return -ENODEV; } }
/** * p1022ds_set_monitor_port: switch the output to a different monitor port */ static void p1022ds_set_monitor_port(enum fsl_diu_monitor_port port) { struct device_node *guts_node; struct device_node *lbc_node = NULL; struct device_node *law_node = NULL; struct ccsr_guts __iomem *guts; struct fsl_lbc_regs *lbc = NULL; void *ecm = NULL; u8 __iomem *lbc_lcs0_ba = NULL; u8 __iomem *lbc_lcs1_ba = NULL; phys_addr_t cs0_addr, cs1_addr; u32 br0, or0, br1, or1; const __be32 *iprop; unsigned int num_laws; u8 b; /* Map the global utilities registers. */ guts_node = of_find_compatible_node(NULL, NULL, "fsl,p1022-guts"); if (!guts_node) { pr_err("p1022ds: missing global utilties device node\n"); return; } guts = of_iomap(guts_node, 0); if (!guts) { pr_err("p1022ds: could not map global utilties device\n"); goto exit; } lbc_node = of_find_compatible_node(NULL, NULL, "fsl,p1022-elbc"); if (!lbc_node) { pr_err("p1022ds: missing localbus node\n"); goto exit; } lbc = of_iomap(lbc_node, 0); if (!lbc) { pr_err("p1022ds: could not map localbus node\n"); goto exit; } law_node = of_find_compatible_node(NULL, NULL, "fsl,ecm-law"); if (!law_node) { pr_err("p1022ds: missing local access window node\n"); goto exit; } ecm = of_iomap(law_node, 0); if (!ecm) { pr_err("p1022ds: could not map local access window node\n"); goto exit; } iprop = of_get_property(law_node, "fsl,num-laws", 0); if (!iprop) { pr_err("p1022ds: LAW node is missing fsl,num-laws property\n"); goto exit; } num_laws = be32_to_cpup(iprop); /* * Indirect mode requires both BR0 and BR1 to be set to "GPCM", * otherwise writes to these addresses won't actually appear on the * local bus, and so the PIXIS won't see them. * * In FCM mode, writes go to the NAND controller, which does not pass * them to the localbus directly. So we force BR0 and BR1 into GPCM * mode, since we don't care about what's behind the localbus any * more. */ br0 = in_be32(&lbc->bank[0].br); br1 = in_be32(&lbc->bank[1].br); or0 = in_be32(&lbc->bank[0].or); or1 = in_be32(&lbc->bank[1].or); /* Make sure CS0 and CS1 are programmed */ if (!(br0 & BR_V) || !(br1 & BR_V)) { pr_err("p1022ds: CS0 and/or CS1 is not programmed\n"); goto exit; } /* * Use the existing BRx/ORx values if it's already GPCM. Otherwise, * force the values to simple 32KB GPCM windows with the most * conservative timing. */ if ((br0 & BR_MSEL) != BR_MS_GPCM) { br0 = (br0 & BR_BA) | BR_V; or0 = 0xFFFF8000 | 0xFF7; out_be32(&lbc->bank[0].br, br0); out_be32(&lbc->bank[0].or, or0); } if ((br1 & BR_MSEL) != BR_MS_GPCM) { br1 = (br1 & BR_BA) | BR_V; or1 = 0xFFFF8000 | 0xFF7; out_be32(&lbc->bank[1].br, br1); out_be32(&lbc->bank[1].or, or1); } cs0_addr = lbc_br_to_phys(ecm, num_laws, br0); if (!cs0_addr) { pr_err("p1022ds: could not determine physical address for CS0" " (BR0=%08x)\n", br0); goto exit; } cs1_addr = lbc_br_to_phys(ecm, num_laws, br1); if (!cs0_addr) { pr_err("p1022ds: could not determine physical address for CS1" " (BR1=%08x)\n", br1); goto exit; } lbc_lcs0_ba = ioremap(cs0_addr, 1); if (!lbc_lcs0_ba) { pr_err("p1022ds: could not ioremap CS0 address %llx\n", (unsigned long long)cs0_addr); goto exit; } lbc_lcs1_ba = ioremap(cs1_addr, 1); if (!lbc_lcs1_ba) { pr_err("p1022ds: could not ioremap CS1 address %llx\n", (unsigned long long)cs1_addr); goto exit; } /* Make sure we're in indirect mode first. */ if ((in_be32(&guts->pmuxcr) & PMUXCR_ELBCDIU_MASK) != PMUXCR_ELBCDIU_DIU) { struct device_node *pixis_node; void __iomem *pixis; pixis_node = of_find_compatible_node(NULL, NULL, "fsl,p1022ds-fpga"); if (!pixis_node) { pr_err("p1022ds: missing pixis node\n"); goto exit; } pixis = of_iomap(pixis_node, 0); of_node_put(pixis_node); if (!pixis) { pr_err("p1022ds: could not map pixis registers\n"); goto exit; } /* Enable indirect PIXIS mode. */ setbits8(pixis + PX_CTL, PX_CTL_ALTACC); iounmap(pixis); /* Switch the board mux to the DIU */ out_8(lbc_lcs0_ba, PX_BRDCFG0); /* BRDCFG0 */ b = in_8(lbc_lcs1_ba); b |= PX_BRDCFG0_ELBC_DIU; out_8(lbc_lcs1_ba, b); /* Set the chip mux to DIU mode. */ clrsetbits_be32(&guts->pmuxcr, PMUXCR_ELBCDIU_MASK, PMUXCR_ELBCDIU_DIU); in_be32(&guts->pmuxcr); } switch (port) { case FSL_DIU_PORT_DVI: /* Enable the DVI port, disable the DFP and the backlight */ out_8(lbc_lcs0_ba, PX_BRDCFG1); b = in_8(lbc_lcs1_ba); b &= ~(PX_BRDCFG1_DFPEN | PX_BRDCFG1_BACKLIGHT); b |= PX_BRDCFG1_DVIEN; out_8(lbc_lcs1_ba, b); break; case FSL_DIU_PORT_LVDS: /* * LVDS also needs backlight enabled, otherwise the display * will be blank. */ /* Enable the DFP port, disable the DVI and the backlight */ out_8(lbc_lcs0_ba, PX_BRDCFG1); b = in_8(lbc_lcs1_ba); b &= ~PX_BRDCFG1_DVIEN; b |= PX_BRDCFG1_DFPEN | PX_BRDCFG1_BACKLIGHT; out_8(lbc_lcs1_ba, b); break; default: pr_err("p1022ds: unsupported monitor port %i\n", port); } exit: if (lbc_lcs1_ba) iounmap(lbc_lcs1_ba); if (lbc_lcs0_ba) iounmap(lbc_lcs0_ba); if (lbc) iounmap(lbc); if (ecm) iounmap(ecm); if (guts) iounmap(guts); of_node_put(law_node); of_node_put(lbc_node); of_node_put(guts_node); }