^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Copyright (c) 2014, The Linux foundation. All rights reserved.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) #include <linux/clk.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include <linux/err.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/of.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/of_platform.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/platform_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/regmap.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/mfd/syscon.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <dt-bindings/soc/qcom,gsbi.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #define GSBI_CTRL_REG 0x0000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #define GSBI_PROTOCOL_SHIFT 4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #define MAX_GSBI 12
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #define TCSR_ADM_CRCI_BASE 0x70
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) struct crci_config {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) u32 num_rows;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) const u32 (*array)[MAX_GSBI];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) static const u32 crci_ipq8064[][MAX_GSBI] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) 0x000003, 0x00000c, 0x000030, 0x0000c0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) 0x000300, 0x000c00, 0x003000, 0x00c000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) 0x030000, 0x0c0000, 0x300000, 0xc00000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) 0x000003, 0x00000c, 0x000030, 0x0000c0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) 0x000300, 0x000c00, 0x003000, 0x00c000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) 0x030000, 0x0c0000, 0x300000, 0xc00000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) static const struct crci_config config_ipq8064 = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) .num_rows = ARRAY_SIZE(crci_ipq8064),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) .array = crci_ipq8064,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) static const unsigned int crci_apq8064[][MAX_GSBI] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) 0x001800, 0x006000, 0x000030, 0x0000c0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) 0x000300, 0x000400, 0x000000, 0x000000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) 0x000000, 0x000000, 0x000000, 0x000000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) 0x000000, 0x000000, 0x000000, 0x000000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) 0x000000, 0x000020, 0x0000c0, 0x000000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) 0x000000, 0x000000, 0x000000, 0x000000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) static const struct crci_config config_apq8064 = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) .num_rows = ARRAY_SIZE(crci_apq8064),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) .array = crci_apq8064,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) static const unsigned int crci_msm8960[][MAX_GSBI] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) 0x000003, 0x00000c, 0x000030, 0x0000c0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) 0x000300, 0x000400, 0x000000, 0x000000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) 0x000000, 0x000000, 0x000000, 0x000000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) 0x000000, 0x000000, 0x000000, 0x000000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) 0x000000, 0x000020, 0x0000c0, 0x000300,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) 0x001800, 0x006000, 0x000000, 0x000000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) static const struct crci_config config_msm8960 = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) .num_rows = ARRAY_SIZE(crci_msm8960),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) .array = crci_msm8960,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) static const unsigned int crci_msm8660[][MAX_GSBI] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) { /* ADM 0 - B */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) 0x000003, 0x00000c, 0x000030, 0x0000c0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) 0x000300, 0x000c00, 0x003000, 0x00c000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) 0x030000, 0x0c0000, 0x300000, 0xc00000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) { /* ADM 0 - B */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) 0x000003, 0x00000c, 0x000030, 0x0000c0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) 0x000300, 0x000c00, 0x003000, 0x00c000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) 0x030000, 0x0c0000, 0x300000, 0xc00000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) { /* ADM 1 - A */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) 0x000003, 0x00000c, 0x000030, 0x0000c0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) 0x000300, 0x000c00, 0x003000, 0x00c000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) 0x030000, 0x0c0000, 0x300000, 0xc00000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) { /* ADM 1 - B */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) 0x000003, 0x00000c, 0x000030, 0x0000c0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) 0x000300, 0x000c00, 0x003000, 0x00c000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) 0x030000, 0x0c0000, 0x300000, 0xc00000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) static const struct crci_config config_msm8660 = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) .num_rows = ARRAY_SIZE(crci_msm8660),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) .array = crci_msm8660,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) struct gsbi_info {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) struct clk *hclk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) u32 mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) u32 crci;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) struct regmap *tcsr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) static const struct of_device_id tcsr_dt_match[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) { .compatible = "qcom,tcsr-ipq8064", .data = &config_ipq8064},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) { .compatible = "qcom,tcsr-apq8064", .data = &config_apq8064},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) { .compatible = "qcom,tcsr-msm8960", .data = &config_msm8960},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) { .compatible = "qcom,tcsr-msm8660", .data = &config_msm8660},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) { },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) static int gsbi_probe(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) struct device_node *node = pdev->dev.of_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) struct device_node *tcsr_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) const struct of_device_id *match;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) struct resource *res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) void __iomem *base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) struct gsbi_info *gsbi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) int i, ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) u32 mask, gsbi_num;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) const struct crci_config *config = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) gsbi = devm_kzalloc(&pdev->dev, sizeof(*gsbi), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) if (!gsbi)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) base = devm_ioremap_resource(&pdev->dev, res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) if (IS_ERR(base))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) return PTR_ERR(base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) /* get the tcsr node and setup the config and regmap */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) gsbi->tcsr = syscon_regmap_lookup_by_phandle(node, "syscon-tcsr");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) if (!IS_ERR(gsbi->tcsr)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) tcsr_node = of_parse_phandle(node, "syscon-tcsr", 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) if (tcsr_node) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) match = of_match_node(tcsr_dt_match, tcsr_node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) if (match)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) config = match->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) dev_warn(&pdev->dev, "no matching TCSR\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) of_node_put(tcsr_node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) if (of_property_read_u32(node, "cell-index", &gsbi_num)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) dev_err(&pdev->dev, "missing cell-index\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) if (gsbi_num < 1 || gsbi_num > MAX_GSBI) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) dev_err(&pdev->dev, "invalid cell-index\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) if (of_property_read_u32(node, "qcom,mode", &gsbi->mode)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) dev_err(&pdev->dev, "missing mode configuration\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) /* not required, so default to 0 if not present */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) of_property_read_u32(node, "qcom,crci", &gsbi->crci);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) dev_info(&pdev->dev, "GSBI port protocol: %d crci: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) gsbi->mode, gsbi->crci);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) gsbi->hclk = devm_clk_get(&pdev->dev, "iface");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) if (IS_ERR(gsbi->hclk))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) return PTR_ERR(gsbi->hclk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) clk_prepare_enable(gsbi->hclk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) writel_relaxed((gsbi->mode << GSBI_PROTOCOL_SHIFT) | gsbi->crci,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) base + GSBI_CTRL_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) * modify tcsr to reflect mode and ADM CRCI mux
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) * Each gsbi contains a pair of bits, one for RX and one for TX
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) * SPI mode requires both bits cleared, otherwise they are set
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) if (config) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) for (i = 0; i < config->num_rows; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) mask = config->array[i][gsbi_num - 1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) if (gsbi->mode == GSBI_PROT_SPI)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) regmap_update_bits(gsbi->tcsr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) TCSR_ADM_CRCI_BASE + 4 * i, mask, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) regmap_update_bits(gsbi->tcsr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) TCSR_ADM_CRCI_BASE + 4 * i, mask, mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) /* make sure the gsbi control write is not reordered */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) wmb();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) platform_set_drvdata(pdev, gsbi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) ret = of_platform_populate(node, NULL, NULL, &pdev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) clk_disable_unprepare(gsbi->hclk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) static int gsbi_remove(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) struct gsbi_info *gsbi = platform_get_drvdata(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) clk_disable_unprepare(gsbi->hclk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) static const struct of_device_id gsbi_dt_match[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) { .compatible = "qcom,gsbi-v1.0.0", },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) { },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) MODULE_DEVICE_TABLE(of, gsbi_dt_match);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) static struct platform_driver gsbi_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) .name = "gsbi",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) .of_match_table = gsbi_dt_match,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) .probe = gsbi_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) .remove = gsbi_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) module_platform_driver(gsbi_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) MODULE_AUTHOR("Andy Gross <agross@codeaurora.org>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) MODULE_DESCRIPTION("QCOM GSBI driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) MODULE_LICENSE("GPL v2");