summaryrefslogtreecommitdiff
path: root/drivers/platform/sprd/sec_gps_s5n6420.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/platform/sprd/sec_gps_s5n6420.c')
-rwxr-xr-xdrivers/platform/sprd/sec_gps_s5n6420.c140
1 files changed, 140 insertions, 0 deletions
diff --git a/drivers/platform/sprd/sec_gps_s5n6420.c b/drivers/platform/sprd/sec_gps_s5n6420.c
new file mode 100755
index 00000000..61d91ef9
--- /dev/null
+++ b/drivers/platform/sprd/sec_gps_s5n6420.c
@@ -0,0 +1,140 @@
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <soc/sprd/gpio.h>
+#include <linux/of.h>
+#include <linux/of_gpio.h>
+#include <linux/regulator/consumer.h>
+#include <soc/sprd/regulator.h>
+#include <linux/clk.h>
+#include <linux/gpio.h>
+
+static struct device *gps_dev;
+extern struct class *sec_class;
+
+static void 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("clock: failed to get clk_aux0\n");
+ }
+ clk_parent = clk_get(NULL, "ext_32k");
+ if (IS_ERR(clk_parent)) {
+ printk("failed to get parent ext_32k\n");
+ }
+
+ clk_set_parent(gps_clk, clk_parent);
+ clk_set_rate(gps_clk, 32000);
+ if(!clk_prepare_enable(gps_clk))
+ printk("%s: %s enabled!!\n", __func__, clk_32k);
+ //clk_enable(gps_clk);
+}
+
+static int gps_regulator_on(void)
+{
+ int ret = 0;
+ const char *gps_node = "lsi,s5n6420";
+ struct device_node *root_node = NULL;
+ static struct regulator *gps_regulator = NULL;
+ const char *reg = NULL;
+
+ root_node = of_find_compatible_node(NULL, NULL, gps_node);
+ if(!root_node) {
+ WARN(1, "[GPS] failed to get device node of %s\n", gps_node);
+ return -ENODEV;
+ }
+ /* regulator enable from dts */
+ if(of_property_read_string(root_node, "gps-regulator", &reg)) {
+ pr_err("%s: main(1.8v) regulator field is not exsit\n", __func__);
+ ret = -ENODEV;
+ goto err_find_node;
+ } else {
+ gps_regulator = regulator_get(NULL, reg);
+ if (IS_ERR(gps_regulator)){
+ gps_regulator = NULL;
+ return -EIO;
+ } else {
+ regulator_set_voltage(gps_regulator, 1800000, 1800000);
+ if(!regulator_enable(gps_regulator))
+ printk("%s: (%s) main(1.8v) regulator turned ON!!\n", __func__, reg);
+ }
+ }
+ return 0;
+
+err_find_node:
+ of_node_put(root_node);
+ return ret;
+}
+
+static unsigned int gps_pwr_on = 0;
+static unsigned int gps_reset = 0;
+
+static int __init gps_s5n6420_init(void)
+{
+ pr_info("%s\n", __func__);
+ gps_regulator_on();
+ gps_clk_init();
+
+ int ret = 0;
+ const char *gps_node = "lsi,s5n6420";
+ const char *gps_pwr_en = "gps-pwr-en";
+ const char *gps_nRst = "gps-reset";
+ struct device_node *root_node = NULL;
+
+ 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) {
+ WARN(1, "failed to get device node of bcm4752\n");
+ ret = -ENODEV;
+ goto err_sec_device_create;
+ }
+
+ gps_pwr_on = of_get_named_gpio(root_node, gps_pwr_en, 0);
+ if(!gpio_is_valid(gps_pwr_on)) {
+ WARN(1, "Invalid gpio pin : %d\n", gps_pwr_on);
+ ret = -ENODEV;
+ goto err_find_node;
+ }
+ if (gpio_request(gps_pwr_on, "GPS_PWR_EN")) {
+ WARN(1, "fail to request gpio(GPS_PWR_EN)\n");
+ ret = -ENODEV;
+ goto err_find_node;
+ }
+ gps_reset= of_get_named_gpio(root_node, gps_nRst, 0);
+ if(!gpio_is_valid(gps_reset)) {
+ WARN(1, "Invalid gpio pin : %d\n", gps_reset);
+ ret = -ENODEV;
+ goto err_find_node;
+ }
+ if (gpio_request(gps_reset, "GPS_RESET")) {
+ WARN(1, "fail to request gpio(GPS_RESET)\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);
+
+ gpio_direction_output(gps_reset, 1);
+ gpio_export(gps_reset, 1);
+ gpio_export_link(gps_dev, "GPS_RESET", gps_reset);
+
+ return 0;
+
+err_find_node:
+ of_node_put(root_node);
+err_sec_device_create:
+ device_destroy(gps_dev, gps_dev->devt);
+ return ret;
+}
+
+device_initcall(gps_s5n6420_init);