rk3288_spi: Add SPI driver
authorVladimir Serbinenko <phcoder@gmail.com>
Tue, 9 May 2017 06:42:14 +0000 (08:42 +0200)
committerVladimir Serbinenko <phcoder@gmail.com>
Tue, 9 May 2017 06:44:23 +0000 (08:44 +0200)
grub-core/Makefile.core.def
grub-core/bus/spi/rk3288_spi.c [new file with mode: 0644]
grub-core/kern/arm/coreboot/init.c
include/grub/arm/coreboot/kernel.h

index 5ce5065..d2239f1 100644 (file)
@@ -162,6 +162,7 @@ kernel = {
   arm_coreboot = bus/fdt.c;
   arm_coreboot = term/ps2.c;
   arm_coreboot = term/arm/pl050.c;
+  arm_coreboot = bus/spi/rk3288_spi.c;
   arm_coreboot = commands/keylayouts.c;
   arm_coreboot = kern/arm/coreboot/dma.c;
 
diff --git a/grub-core/bus/spi/rk3288_spi.c b/grub-core/bus/spi/rk3288_spi.c
new file mode 100644 (file)
index 0000000..aacb79f
--- /dev/null
@@ -0,0 +1,103 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *
+ *  Copyright (C) 2012  Google Inc.
+ *  Copyright (C) 2016  Free Software Foundation, Inc.
+ *
+ *  This is based on depthcharge code.
+ *
+ *  GRUB is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  GRUB is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/mm.h>
+#include <grub/time.h>
+#include <grub/misc.h>
+#include <grub/fdtbus.h>
+#include <grub/machine/kernel.h>
+
+static grub_err_t
+spi_send (const struct grub_fdtbus_dev *dev, const void *data, grub_size_t sz)
+{
+  const grub_uint8_t *ptr = data, *end = ptr + sz;
+  volatile grub_uint32_t *spi = grub_fdtbus_map_reg (dev, 0, 0);
+  spi[2] = 0;
+  spi[1] = sz - 1;
+  spi[0] = ((1 << 18) | spi[0]) & ~(1 << 19);
+  spi[2] = 1;
+  while (ptr < end)
+    {
+      while (spi[9] & 2);
+      spi[256] = *ptr++;
+    }
+  while (spi[9] & 1);
+  return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+spi_receive (const struct grub_fdtbus_dev *dev, void *data, grub_size_t sz)
+{
+  grub_uint8_t *ptr = data, *end = ptr + sz;
+  volatile grub_uint32_t *spi = grub_fdtbus_map_reg (dev, 0, 0);
+  spi[2] = 0;
+  spi[1] = sz - 1;
+  spi[0] = ((1 << 19) | spi[0]) & ~(1 << 18);
+  spi[2] = 1;
+  while (ptr < end)
+    {
+      while (spi[9] & 8);
+      *ptr++ = spi[512];
+    }
+  while (spi[9] & 1);
+  return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+spi_start (const struct grub_fdtbus_dev *dev)
+{
+  volatile grub_uint32_t *spi = grub_fdtbus_map_reg (dev, 0, 0);
+  spi[3] = 1;
+  return GRUB_ERR_NONE;
+}
+
+static void
+spi_stop (const struct grub_fdtbus_dev *dev)
+{
+  volatile grub_uint32_t *spi = grub_fdtbus_map_reg (dev, 0, 0);
+  spi[3] = 0;
+}
+
+static grub_err_t
+spi_attach(const struct grub_fdtbus_dev *dev)
+{
+  if (!grub_fdtbus_is_mapping_valid (grub_fdtbus_map_reg (dev, 0, 0)))
+    return GRUB_ERR_IO;
+
+  return GRUB_ERR_NONE;
+}
+
+static struct grub_fdtbus_driver spi =
+{
+  .compatible = "rockchip,rk3288-spi",
+  .attach = spi_attach,
+  .send = spi_send,
+  .receive = spi_receive,
+  .start = spi_start,
+  .stop = spi_stop,
+};
+
+void
+grub_rk3288_spi_init (void)
+{
+  grub_fdtbus_register (&spi);
+}
index a06ccb7..0126ff6 100644 (file)
@@ -132,6 +132,8 @@ grub_machine_init (void)
     grub_fatal ("No DTB found");
   grub_fdtbus_init (dtb, dtb_size);
 
+  grub_rk3288_spi_init ();
+
   grub_machine_timer_init ();
   grub_pl050_init ();
 }
index 09cd7fe..2695053 100644 (file)
@@ -34,8 +34,8 @@ struct grub_fdt_board
 extern struct grub_fdt_board grub_fdt_boards[];
 void grub_machine_timer_init (void);
 void grub_pl050_init (void);
-void
-grub_cros_init (void);
+void grub_cros_init (void);
+void grub_rk3288_spi_init (void);
 extern grub_addr_t EXPORT_VAR (start_of_ram);
 #endif /* ! ASM_FILE */