summaryrefslogtreecommitdiff
path: root/arch/arm/mach-sc/sec_gps_bcm47520.c
blob: 4431fda6351635c3755427f568f581bca8f12f61 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
#include <linux/platform_device.h>
#include <linux/io.h>
#include <linux/gpio.h>
#include <linux/of.h>
#include <linux/of_gpio.h>
#include <asm/uaccess.h>
//#include "devices.h"
#include <soc/sprd/board.h>
#include <linux/regulator/consumer.h>
#include <soc/sprd/regulator.h>
#include <linux/errno.h>
#include <linux/err.h>
#include <linux/types.h>
#include <linux/clk.h>
#include <soc/sprd/pinmap.h>
#include <linux/proc_fs.h>
#include <linux/irq.h>

static struct device *gps_dev;
extern struct class *sec_class;

static int gps_clk_init(void)
{
    struct clk *gps_clk;
    struct clk *clk_parent;
    const char *clk_32k= "clk_aux0";

    gps_clk = clk_get(NULL, clk_32k);
    if (IS_ERR(gps_clk)) {
        printk("%s: failed to get clk_aux0.\n", __func__);
        return -1;
    }
    clk_parent = clk_get(NULL, "ext_32k");
    if (IS_ERR(clk_parent)) {
        printk("%s: failed to get parent ext_32k.\n", __func__);
        return -1;
    } else {
        clk_set_parent(gps_clk, clk_parent);
        clk_set_rate(gps_clk, 32000);
        if(!clk_prepare_enable(gps_clk))
            pr_info("%s: %s enabled!!\n", __func__, clk_32k);
        //clk_enable(gps_clk);
    }
    return 0;
}

static int gps_regulator_on(struct device_node *root_node)
{
    static struct regulator *gps_regulator = NULL;
    static struct regulator *tcxo_regulator = NULL;
    static unsigned int gps_regulator_volt = 1800000;
    static unsigned int tcxo_regulator_volt = 0;
    const char *reg = NULL;
    const char *reg_tcxo = NULL;

    /* regulator enable from dts */
    if(of_property_read_string(root_node, "gps-regulator", &reg)) {
        printk("%s: Failed to get main-regulator from dts.\n", __func__);
        return -1;
    }
    if(of_property_read_string(root_node, "tcxo-regulator", &reg_tcxo))
        printk("%s: tcxo-regulator field is empty from dts.\n", __func__);

    if(gps_regulator == NULL) {
        gps_regulator = regulator_get(NULL, reg);
        if (IS_ERR(gps_regulator)) {
            gps_regulator = NULL;
            return -1;
        }
    }
    if(tcxo_regulator == NULL) {
        tcxo_regulator = regulator_get(NULL, reg_tcxo);
        if(IS_ERR(tcxo_regulator)) {
            tcxo_regulator = NULL;
        }
    }
    regulator_set_voltage(gps_regulator, gps_regulator_volt, gps_regulator_volt);
    if(!regulator_enable(gps_regulator))
        pr_info("%s: (%s) main(%d uV) regulator turned ON!!\n", __func__, reg, gps_regulator_volt);
    if(of_property_read_u32(root_node, "tcxo-regulator-volt", &tcxo_regulator_volt)) {
        printk("%s: tcxo-requlator-volt field is empty from dts.\n", __func__);
        return 0;
    }
    regulator_set_voltage(tcxo_regulator, tcxo_regulator_volt, tcxo_regulator_volt);
    if(!regulator_enable(tcxo_regulator))
        pr_info("%s: (%s) tcxo(%d uV) regulator turned ON!!\n", __func__, reg_tcxo, tcxo_regulator_volt);

    return 0;
}

static unsigned int gps_pwr_on = 0;

static int __init gps_bcm47520_init(void)
{
    const char *gps_node = "broadcom,bcm47520";
    const char *gps_pwr_en = "gps-pwr-en";
    struct device_node *root_node = NULL;
    int ret = 0;

    pr_info("%s\n", __func__);

    BUG_ON(!sec_class);
    gps_dev = device_create(sec_class, NULL, 0, NULL, "gps");
    BUG_ON(!gps_dev);

    root_node = of_find_compatible_node(NULL, NULL, gps_node);
    if(!root_node) {
        printk("failed to get device node of %s\n", gps_node);
        ret = -ENODEV;
        goto err_sec_device_create;
    }
    if(gps_regulator_on(root_node)) {
        printk("gps_regualtor_on() failed\n");
        ret = -ENODEV;
        goto err_find_node;
    }
    if(gps_clk_init()) {
        printk("gps_clk_init() failed\n");
        ret = -ENODEV;
        goto err_find_node;
    }
    gps_pwr_on = of_get_named_gpio(root_node, gps_pwr_en, 0);
    if(!gpio_is_valid(gps_pwr_on)) {
        printk("%s: Invalid gpio pin : %d\n", __func__, gps_pwr_on);
        ret = -ENODEV;
        goto err_find_node;
    }
    if (gpio_request(gps_pwr_on, "GPS_PWR_EN")) {
        printk("fail to request gpio(GPS_PWR_EN)\n");
        ret = -ENODEV;
        goto err_find_node;
    }
    gpio_direction_output(gps_pwr_on, 0);
    gpio_export(gps_pwr_on, 1);
    gpio_export_link(gps_dev, "GPS_PWR_EN", gps_pwr_on);

    return 0;

err_find_node:
    of_node_put(root_node);
err_sec_device_create:
    device_destroy(sec_class, gps_dev->devt);
    return ret;
}

device_initcall(gps_bcm47520_init);