Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: ISC
0002 /*
0003  * Copyright (c) 2014 Broadcom Corporation
0004  */
0005 #include <linux/init.h>
0006 #include <linux/of.h>
0007 #include <linux/of_irq.h>
0008 #include <linux/of_net.h>
0009 
0010 #include <defs.h>
0011 #include "debug.h"
0012 #include "core.h"
0013 #include "common.h"
0014 #include "of.h"
0015 
0016 static int brcmf_of_get_country_codes(struct device *dev,
0017                       struct brcmf_mp_device *settings)
0018 {
0019     struct device_node *np = dev->of_node;
0020     struct brcmfmac_pd_cc_entry *cce;
0021     struct brcmfmac_pd_cc *cc;
0022     int count;
0023     int i;
0024 
0025     count = of_property_count_strings(np, "brcm,ccode-map");
0026     if (count < 0) {
0027         /* If no explicit country code map is specified, check whether
0028          * the trivial map should be used.
0029          */
0030         settings->trivial_ccode_map =
0031             of_property_read_bool(np, "brcm,ccode-map-trivial");
0032 
0033         /* The property is optional, so return success if it doesn't
0034          * exist. Otherwise propagate the error code.
0035          */
0036         return (count == -EINVAL) ? 0 : count;
0037     }
0038 
0039     cc = devm_kzalloc(dev, struct_size(cc, table, count), GFP_KERNEL);
0040     if (!cc)
0041         return -ENOMEM;
0042 
0043     cc->table_size = count;
0044 
0045     for (i = 0; i < count; i++) {
0046         const char *map;
0047 
0048         cce = &cc->table[i];
0049 
0050         if (of_property_read_string_index(np, "brcm,ccode-map",
0051                           i, &map))
0052             continue;
0053 
0054         /* String format e.g. US-Q2-86 */
0055         if (sscanf(map, "%2c-%2c-%d", cce->iso3166, cce->cc,
0056                &cce->rev) != 3)
0057             brcmf_err("failed to read country map %s\n", map);
0058         else
0059             brcmf_dbg(INFO, "%s-%s-%d\n", cce->iso3166, cce->cc,
0060                   cce->rev);
0061     }
0062 
0063     settings->country_codes = cc;
0064 
0065     return 0;
0066 }
0067 
0068 void brcmf_of_probe(struct device *dev, enum brcmf_bus_type bus_type,
0069             struct brcmf_mp_device *settings)
0070 {
0071     struct brcmfmac_sdio_pd *sdio = &settings->bus.sdio;
0072     struct device_node *root, *np = dev->of_node;
0073     int irq;
0074     int err;
0075     u32 irqf;
0076     u32 val;
0077 
0078     /* Set board-type to the first string of the machine compatible prop */
0079     root = of_find_node_by_path("/");
0080     if (root) {
0081         char *board_type;
0082         const char *tmp;
0083 
0084         of_property_read_string_index(root, "compatible", 0, &tmp);
0085 
0086         /* get rid of '/' in the compatible string to be able to find the FW */
0087         board_type = devm_kstrdup(dev, tmp, GFP_KERNEL);
0088         if (!board_type) {
0089             of_node_put(root);
0090             return;
0091         }
0092         strreplace(board_type, '/', '-');
0093         settings->board_type = board_type;
0094 
0095         of_node_put(root);
0096     }
0097 
0098     if (!np || !of_device_is_compatible(np, "brcm,bcm4329-fmac"))
0099         return;
0100 
0101     err = brcmf_of_get_country_codes(dev, settings);
0102     if (err)
0103         brcmf_err("failed to get OF country code map (err=%d)\n", err);
0104 
0105     of_get_mac_address(np, settings->mac);
0106 
0107     if (bus_type != BRCMF_BUSTYPE_SDIO)
0108         return;
0109 
0110     if (of_property_read_u32(np, "brcm,drive-strength", &val) == 0)
0111         sdio->drive_strength = val;
0112 
0113     /* make sure there are interrupts defined in the node */
0114     if (!of_find_property(np, "interrupts", NULL))
0115         return;
0116 
0117     irq = irq_of_parse_and_map(np, 0);
0118     if (!irq) {
0119         brcmf_err("interrupt could not be mapped\n");
0120         return;
0121     }
0122     irqf = irqd_get_trigger_type(irq_get_irq_data(irq));
0123 
0124     sdio->oob_irq_supported = true;
0125     sdio->oob_irq_nr = irq;
0126     sdio->oob_irq_flags = irqf;
0127 }