0005-ARM-qcom-Split-Qualcomm-support-into-legacy-and-mult.patch 38 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423
  1. From 8c2a00c0129d6f718245f7a613c2bb28976b7973 Mon Sep 17 00:00:00 2001
  2. From: Kumar Gala <[email protected]>
  3. Date: Tue, 21 Jan 2014 17:14:10 -0600
  4. Subject: [PATCH 005/182] ARM: qcom: Split Qualcomm support into legacy and
  5. multiplatform
  6. Introduce a new mach-qcom that will support SoCs that intend to be
  7. multiplatform compatible while keeping mach-msm to legacy SoC/board
  8. support that will not transition over to multiplatform.
  9. As part of this, we move support for MSM8X60, MSM8960 and MSM8974 over
  10. to mach-qcom.
  11. Signed-off-by: Kumar Gala <[email protected]>
  12. ---
  13. MAINTAINERS | 8 ++
  14. arch/arm/Kconfig | 7 +-
  15. arch/arm/Kconfig.debug | 2 +-
  16. arch/arm/Makefile | 1 +
  17. arch/arm/boot/dts/Makefile | 6 +-
  18. arch/arm/mach-msm/Kconfig | 45 +------
  19. arch/arm/mach-msm/Makefile | 6 -
  20. arch/arm/mach-msm/board-dt.c | 41 ------
  21. arch/arm/mach-msm/platsmp.c | 137 -------------------
  22. arch/arm/mach-msm/scm-boot.c | 39 ------
  23. arch/arm/mach-msm/scm-boot.h | 22 ---
  24. arch/arm/mach-msm/scm.c | 299 -----------------------------------------
  25. arch/arm/mach-msm/scm.h | 25 ----
  26. arch/arm/mach-qcom/Kconfig | 33 +++++
  27. arch/arm/mach-qcom/Makefile | 5 +
  28. arch/arm/mach-qcom/board.c | 40 ++++++
  29. arch/arm/mach-qcom/platsmp.c | 137 +++++++++++++++++++
  30. arch/arm/mach-qcom/scm-boot.c | 39 ++++++
  31. arch/arm/mach-qcom/scm-boot.h | 22 +++
  32. arch/arm/mach-qcom/scm.c | 299 +++++++++++++++++++++++++++++++++++++++++
  33. arch/arm/mach-qcom/scm.h | 25 ++++
  34. 21 files changed, 619 insertions(+), 619 deletions(-)
  35. delete mode 100644 arch/arm/mach-msm/board-dt.c
  36. delete mode 100644 arch/arm/mach-msm/platsmp.c
  37. delete mode 100644 arch/arm/mach-msm/scm-boot.c
  38. delete mode 100644 arch/arm/mach-msm/scm-boot.h
  39. delete mode 100644 arch/arm/mach-msm/scm.c
  40. delete mode 100644 arch/arm/mach-msm/scm.h
  41. create mode 100644 arch/arm/mach-qcom/Kconfig
  42. create mode 100644 arch/arm/mach-qcom/Makefile
  43. create mode 100644 arch/arm/mach-qcom/board.c
  44. create mode 100644 arch/arm/mach-qcom/platsmp.c
  45. create mode 100644 arch/arm/mach-qcom/scm-boot.c
  46. create mode 100644 arch/arm/mach-qcom/scm-boot.h
  47. create mode 100644 arch/arm/mach-qcom/scm.c
  48. create mode 100644 arch/arm/mach-qcom/scm.h
  49. --- a/MAINTAINERS
  50. +++ b/MAINTAINERS
  51. @@ -1168,6 +1168,14 @@ L: [email protected]
  52. W: http://www.arm.linux.org.uk/
  53. S: Maintained
  54. +ARM/QUALCOMM SUPPORT
  55. +M: Kumar Gala <[email protected]>
  56. +M: David Brown <[email protected]>
  57. +L: [email protected]
  58. +S: Maintained
  59. +F: arch/arm/mach-qcom/
  60. +T: git git://git.kernel.org/pub/scm/linux/kernel/git/galak/linux-qcom.git
  61. +
  62. ARM/RADISYS ENP2611 MACHINE SUPPORT
  63. M: Lennert Buytenhek <[email protected]>
  64. L: [email protected] (moderated for non-subscribers)
  65. --- a/arch/arm/Kconfig
  66. +++ b/arch/arm/Kconfig
  67. @@ -658,9 +658,8 @@ config ARCH_PXA
  68. help
  69. Support for Intel/Marvell's PXA2xx/PXA3xx processor line.
  70. -config ARCH_MSM_NODT
  71. - bool "Qualcomm MSM"
  72. - select ARCH_MSM
  73. +config ARCH_MSM
  74. + bool "Qualcomm MSM (non-multiplatform)"
  75. select ARCH_REQUIRE_GPIOLIB
  76. select COMMON_CLK
  77. select GENERIC_CLOCKEVENTS
  78. @@ -1006,6 +1005,8 @@ source "arch/arm/plat-pxa/Kconfig"
  79. source "arch/arm/mach-mmp/Kconfig"
  80. +source "arch/arm/mach-qcom/Kconfig"
  81. +
  82. source "arch/arm/mach-realview/Kconfig"
  83. source "arch/arm/mach-rockchip/Kconfig"
  84. --- a/arch/arm/Kconfig.debug
  85. +++ b/arch/arm/Kconfig.debug
  86. @@ -956,7 +956,7 @@ config DEBUG_STI_UART
  87. config DEBUG_MSM_UART
  88. bool
  89. - depends on ARCH_MSM
  90. + depends on ARCH_MSM || ARCH_QCOM
  91. config DEBUG_LL_INCLUDE
  92. string
  93. --- a/arch/arm/Makefile
  94. +++ b/arch/arm/Makefile
  95. @@ -185,6 +185,7 @@ machine-$(CONFIG_ARCH_OMAP2PLUS) += omap
  96. machine-$(CONFIG_ARCH_ORION5X) += orion5x
  97. machine-$(CONFIG_ARCH_PICOXCELL) += picoxcell
  98. machine-$(CONFIG_ARCH_PXA) += pxa
  99. +machine-$(CONFIG_ARCH_QCOM) += qcom
  100. machine-$(CONFIG_ARCH_REALVIEW) += realview
  101. machine-$(CONFIG_ARCH_ROCKCHIP) += rockchip
  102. machine-$(CONFIG_ARCH_RPC) += rpc
  103. --- a/arch/arm/boot/dts/Makefile
  104. +++ b/arch/arm/boot/dts/Makefile
  105. @@ -119,9 +119,6 @@ dtb-$(CONFIG_ARCH_KIRKWOOD) += kirkwood-
  106. kirkwood-ts219-6282.dtb
  107. dtb-$(CONFIG_ARCH_MARCO) += marco-evb.dtb
  108. dtb-$(CONFIG_ARCH_MOXART) += moxart-uc7112lx.dtb
  109. -dtb-$(CONFIG_ARCH_MSM) += qcom-msm8660-surf.dtb \
  110. - qcom-msm8960-cdp.dtb \
  111. - qcom-apq8074-dragonboard.dtb
  112. dtb-$(CONFIG_ARCH_MVEBU) += armada-370-db.dtb \
  113. armada-370-mirabox.dtb \
  114. armada-370-netgear-rn102.dtb \
  115. @@ -234,6 +231,9 @@ dtb-$(CONFIG_ARCH_OMAP2PLUS) += omap2420
  116. dra7-evm.dtb
  117. dtb-$(CONFIG_ARCH_ORION5X) += orion5x-lacie-ethernet-disk-mini-v2.dtb
  118. dtb-$(CONFIG_ARCH_PRIMA2) += prima2-evb.dtb
  119. +dtb-$(CONFIG_ARCH_QCOM) += qcom-msm8660-surf.dtb \
  120. + qcom-msm8960-cdp.dtb \
  121. + qcom-apq8074-dragonboard.dtb
  122. dtb-$(CONFIG_ARCH_U8500) += ste-snowball.dtb \
  123. ste-hrefprev60-stuib.dtb \
  124. ste-hrefprev60-tvk.dtb \
  125. --- a/arch/arm/mach-msm/Kconfig
  126. +++ b/arch/arm/mach-msm/Kconfig
  127. @@ -1,50 +1,9 @@
  128. -config ARCH_MSM
  129. - bool
  130. -
  131. -config ARCH_MSM_DT
  132. - bool "Qualcomm MSM DT Support" if ARCH_MULTI_V7
  133. - select ARCH_MSM
  134. - select ARCH_REQUIRE_GPIOLIB
  135. - select CLKSRC_OF
  136. - select GENERIC_CLOCKEVENTS
  137. - help
  138. - Support for Qualcomm's devicetree based MSM systems.
  139. -
  140. if ARCH_MSM
  141. -menu "Qualcomm MSM SoC Selection"
  142. - depends on ARCH_MSM_DT
  143. -
  144. -config ARCH_MSM8X60
  145. - bool "Enable support for MSM8X60"
  146. - select ARM_GIC
  147. - select CPU_V7
  148. - select HAVE_SMP
  149. - select MSM_SCM if SMP
  150. - select CLKSRC_QCOM
  151. -
  152. -config ARCH_MSM8960
  153. - bool "Enable support for MSM8960"
  154. - select ARM_GIC
  155. - select CPU_V7
  156. - select HAVE_SMP
  157. - select MSM_SCM if SMP
  158. - select CLKSRC_QCOM
  159. -
  160. -config ARCH_MSM8974
  161. - bool "Enable support for MSM8974"
  162. - select ARM_GIC
  163. - select CPU_V7
  164. - select HAVE_ARM_ARCH_TIMER
  165. - select HAVE_SMP
  166. - select MSM_SCM if SMP
  167. -
  168. -endmenu
  169. -
  170. choice
  171. prompt "Qualcomm MSM SoC Type"
  172. default ARCH_MSM7X00A
  173. - depends on ARCH_MSM_NODT
  174. + depends on ARCH_MSM
  175. config ARCH_MSM7X00A
  176. bool "MSM7x00A / MSM7x01A"
  177. @@ -99,7 +58,7 @@ config MSM_VIC
  178. bool
  179. menu "Qualcomm MSM Board Type"
  180. - depends on ARCH_MSM_NODT
  181. + depends on ARCH_MSM
  182. config MACH_HALIBUT
  183. depends on ARCH_MSM
  184. --- a/arch/arm/mach-msm/Makefile
  185. +++ b/arch/arm/mach-msm/Makefile
  186. @@ -13,17 +13,11 @@ obj-$(CONFIG_ARCH_QSD8X50) += dma.o io.o
  187. obj-$(CONFIG_MSM_SMD) += smd.o smd_debug.o
  188. obj-$(CONFIG_MSM_SMD) += last_radio_log.o
  189. -obj-$(CONFIG_MSM_SCM) += scm.o scm-boot.o
  190. -
  191. -CFLAGS_scm.o :=$(call as-instr,.arch_extension sec,-DREQUIRES_SEC=1)
  192. -
  193. -obj-$(CONFIG_SMP) += platsmp.o
  194. obj-$(CONFIG_MACH_TROUT) += board-trout.o board-trout-gpio.o board-trout-mmc.o devices-msm7x00.o
  195. obj-$(CONFIG_MACH_TROUT) += board-trout.o board-trout-gpio.o board-trout-mmc.o board-trout-panel.o devices-msm7x00.o
  196. obj-$(CONFIG_MACH_HALIBUT) += board-halibut.o devices-msm7x00.o
  197. obj-$(CONFIG_ARCH_MSM7X30) += board-msm7x30.o devices-msm7x30.o
  198. obj-$(CONFIG_ARCH_QSD8X50) += board-qsd8x50.o devices-qsd8x50.o
  199. -obj-$(CONFIG_ARCH_MSM_DT) += board-dt.o
  200. obj-$(CONFIG_MSM_GPIOMUX) += gpiomux.o
  201. obj-$(CONFIG_ARCH_QSD8X50) += gpiomux-8x50.o
  202. --- a/arch/arm/mach-msm/board-dt.c
  203. +++ /dev/null
  204. @@ -1,41 +0,0 @@
  205. -/* Copyright (c) 2010-2012,2013 The Linux Foundation. All rights reserved.
  206. - *
  207. - * This program is free software; you can redistribute it and/or modify
  208. - * it under the terms of the GNU General Public License version 2 and
  209. - * only version 2 as published by the Free Software Foundation.
  210. - *
  211. - * This program is distributed in the hope that it will be useful,
  212. - * but WITHOUT ANY WARRANTY; without even the implied warranty of
  213. - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  214. - * GNU General Public License for more details.
  215. - */
  216. -
  217. -#include <linux/init.h>
  218. -#include <linux/of.h>
  219. -#include <linux/of_platform.h>
  220. -
  221. -#include <asm/mach/arch.h>
  222. -#include <asm/mach/map.h>
  223. -
  224. -#include "common.h"
  225. -
  226. -static const char * const msm_dt_match[] __initconst = {
  227. - "qcom,msm8660-fluid",
  228. - "qcom,msm8660-surf",
  229. - "qcom,msm8960-cdp",
  230. - NULL
  231. -};
  232. -
  233. -static const char * const apq8074_dt_match[] __initconst = {
  234. - "qcom,apq8074-dragonboard",
  235. - NULL
  236. -};
  237. -
  238. -DT_MACHINE_START(MSM_DT, "Qualcomm MSM (Flattened Device Tree)")
  239. - .smp = smp_ops(msm_smp_ops),
  240. - .dt_compat = msm_dt_match,
  241. -MACHINE_END
  242. -
  243. -DT_MACHINE_START(APQ_DT, "Qualcomm MSM (Flattened Device Tree)")
  244. - .dt_compat = apq8074_dt_match,
  245. -MACHINE_END
  246. --- a/arch/arm/mach-msm/platsmp.c
  247. +++ /dev/null
  248. @@ -1,137 +0,0 @@
  249. -/*
  250. - * Copyright (C) 2002 ARM Ltd.
  251. - * All Rights Reserved
  252. - * Copyright (c) 2010, Code Aurora Forum. All rights reserved.
  253. - *
  254. - * This program is free software; you can redistribute it and/or modify
  255. - * it under the terms of the GNU General Public License version 2 as
  256. - * published by the Free Software Foundation.
  257. - */
  258. -
  259. -#include <linux/init.h>
  260. -#include <linux/errno.h>
  261. -#include <linux/delay.h>
  262. -#include <linux/device.h>
  263. -#include <linux/smp.h>
  264. -#include <linux/io.h>
  265. -
  266. -#include <asm/cputype.h>
  267. -#include <asm/smp_plat.h>
  268. -
  269. -#include "scm-boot.h"
  270. -#include "common.h"
  271. -
  272. -#define VDD_SC1_ARRAY_CLAMP_GFS_CTL 0x15A0
  273. -#define SCSS_CPU1CORE_RESET 0xD80
  274. -#define SCSS_DBG_STATUS_CORE_PWRDUP 0xE64
  275. -
  276. -extern void secondary_startup(void);
  277. -
  278. -static DEFINE_SPINLOCK(boot_lock);
  279. -
  280. -#ifdef CONFIG_HOTPLUG_CPU
  281. -static void __ref msm_cpu_die(unsigned int cpu)
  282. -{
  283. - wfi();
  284. -}
  285. -#endif
  286. -
  287. -static inline int get_core_count(void)
  288. -{
  289. - /* 1 + the PART[1:0] field of MIDR */
  290. - return ((read_cpuid_id() >> 4) & 3) + 1;
  291. -}
  292. -
  293. -static void msm_secondary_init(unsigned int cpu)
  294. -{
  295. - /*
  296. - * Synchronise with the boot thread.
  297. - */
  298. - spin_lock(&boot_lock);
  299. - spin_unlock(&boot_lock);
  300. -}
  301. -
  302. -static void prepare_cold_cpu(unsigned int cpu)
  303. -{
  304. - int ret;
  305. - ret = scm_set_boot_addr(virt_to_phys(secondary_startup),
  306. - SCM_FLAG_COLDBOOT_CPU1);
  307. - if (ret == 0) {
  308. - void __iomem *sc1_base_ptr;
  309. - sc1_base_ptr = ioremap_nocache(0x00902000, SZ_4K*2);
  310. - if (sc1_base_ptr) {
  311. - writel(0, sc1_base_ptr + VDD_SC1_ARRAY_CLAMP_GFS_CTL);
  312. - writel(0, sc1_base_ptr + SCSS_CPU1CORE_RESET);
  313. - writel(3, sc1_base_ptr + SCSS_DBG_STATUS_CORE_PWRDUP);
  314. - iounmap(sc1_base_ptr);
  315. - }
  316. - } else
  317. - printk(KERN_DEBUG "Failed to set secondary core boot "
  318. - "address\n");
  319. -}
  320. -
  321. -static int msm_boot_secondary(unsigned int cpu, struct task_struct *idle)
  322. -{
  323. - static int cold_boot_done;
  324. -
  325. - /* Only need to bring cpu out of reset this way once */
  326. - if (cold_boot_done == false) {
  327. - prepare_cold_cpu(cpu);
  328. - cold_boot_done = true;
  329. - }
  330. -
  331. - /*
  332. - * set synchronisation state between this boot processor
  333. - * and the secondary one
  334. - */
  335. - spin_lock(&boot_lock);
  336. -
  337. - /*
  338. - * Send the secondary CPU a soft interrupt, thereby causing
  339. - * the boot monitor to read the system wide flags register,
  340. - * and branch to the address found there.
  341. - */
  342. - arch_send_wakeup_ipi_mask(cpumask_of(cpu));
  343. -
  344. - /*
  345. - * now the secondary core is starting up let it run its
  346. - * calibrations, then wait for it to finish
  347. - */
  348. - spin_unlock(&boot_lock);
  349. -
  350. - return 0;
  351. -}
  352. -
  353. -/*
  354. - * Initialise the CPU possible map early - this describes the CPUs
  355. - * which may be present or become present in the system. The msm8x60
  356. - * does not support the ARM SCU, so just set the possible cpu mask to
  357. - * NR_CPUS.
  358. - */
  359. -static void __init msm_smp_init_cpus(void)
  360. -{
  361. - unsigned int i, ncores = get_core_count();
  362. -
  363. - if (ncores > nr_cpu_ids) {
  364. - pr_warn("SMP: %u cores greater than maximum (%u), clipping\n",
  365. - ncores, nr_cpu_ids);
  366. - ncores = nr_cpu_ids;
  367. - }
  368. -
  369. - for (i = 0; i < ncores; i++)
  370. - set_cpu_possible(i, true);
  371. -}
  372. -
  373. -static void __init msm_smp_prepare_cpus(unsigned int max_cpus)
  374. -{
  375. -}
  376. -
  377. -struct smp_operations msm_smp_ops __initdata = {
  378. - .smp_init_cpus = msm_smp_init_cpus,
  379. - .smp_prepare_cpus = msm_smp_prepare_cpus,
  380. - .smp_secondary_init = msm_secondary_init,
  381. - .smp_boot_secondary = msm_boot_secondary,
  382. -#ifdef CONFIG_HOTPLUG_CPU
  383. - .cpu_die = msm_cpu_die,
  384. -#endif
  385. -};
  386. --- a/arch/arm/mach-msm/scm-boot.c
  387. +++ /dev/null
  388. @@ -1,39 +0,0 @@
  389. -/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
  390. - *
  391. - * This program is free software; you can redistribute it and/or modify
  392. - * it under the terms of the GNU General Public License version 2 and
  393. - * only version 2 as published by the Free Software Foundation.
  394. - *
  395. - * This program is distributed in the hope that it will be useful,
  396. - * but WITHOUT ANY WARRANTY; without even the implied warranty of
  397. - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  398. - * GNU General Public License for more details.
  399. - *
  400. - * You should have received a copy of the GNU General Public License
  401. - * along with this program; if not, write to the Free Software
  402. - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  403. - * 02110-1301, USA.
  404. - */
  405. -
  406. -#include <linux/module.h>
  407. -#include <linux/slab.h>
  408. -
  409. -#include "scm.h"
  410. -#include "scm-boot.h"
  411. -
  412. -/*
  413. - * Set the cold/warm boot address for one of the CPU cores.
  414. - */
  415. -int scm_set_boot_addr(phys_addr_t addr, int flags)
  416. -{
  417. - struct {
  418. - unsigned int flags;
  419. - phys_addr_t addr;
  420. - } cmd;
  421. -
  422. - cmd.addr = addr;
  423. - cmd.flags = flags;
  424. - return scm_call(SCM_SVC_BOOT, SCM_BOOT_ADDR,
  425. - &cmd, sizeof(cmd), NULL, 0);
  426. -}
  427. -EXPORT_SYMBOL(scm_set_boot_addr);
  428. --- a/arch/arm/mach-msm/scm-boot.h
  429. +++ /dev/null
  430. @@ -1,22 +0,0 @@
  431. -/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
  432. - *
  433. - * This program is free software; you can redistribute it and/or modify
  434. - * it under the terms of the GNU General Public License version 2 and
  435. - * only version 2 as published by the Free Software Foundation.
  436. - *
  437. - * This program is distributed in the hope that it will be useful,
  438. - * but WITHOUT ANY WARRANTY; without even the implied warranty of
  439. - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  440. - * GNU General Public License for more details.
  441. - */
  442. -#ifndef __MACH_SCM_BOOT_H
  443. -#define __MACH_SCM_BOOT_H
  444. -
  445. -#define SCM_BOOT_ADDR 0x1
  446. -#define SCM_FLAG_COLDBOOT_CPU1 0x1
  447. -#define SCM_FLAG_WARMBOOT_CPU1 0x2
  448. -#define SCM_FLAG_WARMBOOT_CPU0 0x4
  449. -
  450. -int scm_set_boot_addr(phys_addr_t addr, int flags);
  451. -
  452. -#endif
  453. --- a/arch/arm/mach-msm/scm.c
  454. +++ /dev/null
  455. @@ -1,299 +0,0 @@
  456. -/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
  457. - *
  458. - * This program is free software; you can redistribute it and/or modify
  459. - * it under the terms of the GNU General Public License version 2 and
  460. - * only version 2 as published by the Free Software Foundation.
  461. - *
  462. - * This program is distributed in the hope that it will be useful,
  463. - * but WITHOUT ANY WARRANTY; without even the implied warranty of
  464. - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  465. - * GNU General Public License for more details.
  466. - *
  467. - * You should have received a copy of the GNU General Public License
  468. - * along with this program; if not, write to the Free Software
  469. - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  470. - * 02110-1301, USA.
  471. - */
  472. -
  473. -#include <linux/slab.h>
  474. -#include <linux/io.h>
  475. -#include <linux/module.h>
  476. -#include <linux/mutex.h>
  477. -#include <linux/errno.h>
  478. -#include <linux/err.h>
  479. -
  480. -#include <asm/cacheflush.h>
  481. -
  482. -#include "scm.h"
  483. -
  484. -/* Cache line size for msm8x60 */
  485. -#define CACHELINESIZE 32
  486. -
  487. -#define SCM_ENOMEM -5
  488. -#define SCM_EOPNOTSUPP -4
  489. -#define SCM_EINVAL_ADDR -3
  490. -#define SCM_EINVAL_ARG -2
  491. -#define SCM_ERROR -1
  492. -#define SCM_INTERRUPTED 1
  493. -
  494. -static DEFINE_MUTEX(scm_lock);
  495. -
  496. -/**
  497. - * struct scm_command - one SCM command buffer
  498. - * @len: total available memory for command and response
  499. - * @buf_offset: start of command buffer
  500. - * @resp_hdr_offset: start of response buffer
  501. - * @id: command to be executed
  502. - * @buf: buffer returned from scm_get_command_buffer()
  503. - *
  504. - * An SCM command is laid out in memory as follows:
  505. - *
  506. - * ------------------- <--- struct scm_command
  507. - * | command header |
  508. - * ------------------- <--- scm_get_command_buffer()
  509. - * | command buffer |
  510. - * ------------------- <--- struct scm_response and
  511. - * | response header | scm_command_to_response()
  512. - * ------------------- <--- scm_get_response_buffer()
  513. - * | response buffer |
  514. - * -------------------
  515. - *
  516. - * There can be arbitrary padding between the headers and buffers so
  517. - * you should always use the appropriate scm_get_*_buffer() routines
  518. - * to access the buffers in a safe manner.
  519. - */
  520. -struct scm_command {
  521. - u32 len;
  522. - u32 buf_offset;
  523. - u32 resp_hdr_offset;
  524. - u32 id;
  525. - u32 buf[0];
  526. -};
  527. -
  528. -/**
  529. - * struct scm_response - one SCM response buffer
  530. - * @len: total available memory for response
  531. - * @buf_offset: start of response data relative to start of scm_response
  532. - * @is_complete: indicates if the command has finished processing
  533. - */
  534. -struct scm_response {
  535. - u32 len;
  536. - u32 buf_offset;
  537. - u32 is_complete;
  538. -};
  539. -
  540. -/**
  541. - * alloc_scm_command() - Allocate an SCM command
  542. - * @cmd_size: size of the command buffer
  543. - * @resp_size: size of the response buffer
  544. - *
  545. - * Allocate an SCM command, including enough room for the command
  546. - * and response headers as well as the command and response buffers.
  547. - *
  548. - * Returns a valid &scm_command on success or %NULL if the allocation fails.
  549. - */
  550. -static struct scm_command *alloc_scm_command(size_t cmd_size, size_t resp_size)
  551. -{
  552. - struct scm_command *cmd;
  553. - size_t len = sizeof(*cmd) + sizeof(struct scm_response) + cmd_size +
  554. - resp_size;
  555. -
  556. - cmd = kzalloc(PAGE_ALIGN(len), GFP_KERNEL);
  557. - if (cmd) {
  558. - cmd->len = len;
  559. - cmd->buf_offset = offsetof(struct scm_command, buf);
  560. - cmd->resp_hdr_offset = cmd->buf_offset + cmd_size;
  561. - }
  562. - return cmd;
  563. -}
  564. -
  565. -/**
  566. - * free_scm_command() - Free an SCM command
  567. - * @cmd: command to free
  568. - *
  569. - * Free an SCM command.
  570. - */
  571. -static inline void free_scm_command(struct scm_command *cmd)
  572. -{
  573. - kfree(cmd);
  574. -}
  575. -
  576. -/**
  577. - * scm_command_to_response() - Get a pointer to a scm_response
  578. - * @cmd: command
  579. - *
  580. - * Returns a pointer to a response for a command.
  581. - */
  582. -static inline struct scm_response *scm_command_to_response(
  583. - const struct scm_command *cmd)
  584. -{
  585. - return (void *)cmd + cmd->resp_hdr_offset;
  586. -}
  587. -
  588. -/**
  589. - * scm_get_command_buffer() - Get a pointer to a command buffer
  590. - * @cmd: command
  591. - *
  592. - * Returns a pointer to the command buffer of a command.
  593. - */
  594. -static inline void *scm_get_command_buffer(const struct scm_command *cmd)
  595. -{
  596. - return (void *)cmd->buf;
  597. -}
  598. -
  599. -/**
  600. - * scm_get_response_buffer() - Get a pointer to a response buffer
  601. - * @rsp: response
  602. - *
  603. - * Returns a pointer to a response buffer of a response.
  604. - */
  605. -static inline void *scm_get_response_buffer(const struct scm_response *rsp)
  606. -{
  607. - return (void *)rsp + rsp->buf_offset;
  608. -}
  609. -
  610. -static int scm_remap_error(int err)
  611. -{
  612. - switch (err) {
  613. - case SCM_ERROR:
  614. - return -EIO;
  615. - case SCM_EINVAL_ADDR:
  616. - case SCM_EINVAL_ARG:
  617. - return -EINVAL;
  618. - case SCM_EOPNOTSUPP:
  619. - return -EOPNOTSUPP;
  620. - case SCM_ENOMEM:
  621. - return -ENOMEM;
  622. - }
  623. - return -EINVAL;
  624. -}
  625. -
  626. -static u32 smc(u32 cmd_addr)
  627. -{
  628. - int context_id;
  629. - register u32 r0 asm("r0") = 1;
  630. - register u32 r1 asm("r1") = (u32)&context_id;
  631. - register u32 r2 asm("r2") = cmd_addr;
  632. - do {
  633. - asm volatile(
  634. - __asmeq("%0", "r0")
  635. - __asmeq("%1", "r0")
  636. - __asmeq("%2", "r1")
  637. - __asmeq("%3", "r2")
  638. -#ifdef REQUIRES_SEC
  639. - ".arch_extension sec\n"
  640. -#endif
  641. - "smc #0 @ switch to secure world\n"
  642. - : "=r" (r0)
  643. - : "r" (r0), "r" (r1), "r" (r2)
  644. - : "r3");
  645. - } while (r0 == SCM_INTERRUPTED);
  646. -
  647. - return r0;
  648. -}
  649. -
  650. -static int __scm_call(const struct scm_command *cmd)
  651. -{
  652. - int ret;
  653. - u32 cmd_addr = virt_to_phys(cmd);
  654. -
  655. - /*
  656. - * Flush the entire cache here so callers don't have to remember
  657. - * to flush the cache when passing physical addresses to the secure
  658. - * side in the buffer.
  659. - */
  660. - flush_cache_all();
  661. - ret = smc(cmd_addr);
  662. - if (ret < 0)
  663. - ret = scm_remap_error(ret);
  664. -
  665. - return ret;
  666. -}
  667. -
  668. -/**
  669. - * scm_call() - Send an SCM command
  670. - * @svc_id: service identifier
  671. - * @cmd_id: command identifier
  672. - * @cmd_buf: command buffer
  673. - * @cmd_len: length of the command buffer
  674. - * @resp_buf: response buffer
  675. - * @resp_len: length of the response buffer
  676. - *
  677. - * Sends a command to the SCM and waits for the command to finish processing.
  678. - */
  679. -int scm_call(u32 svc_id, u32 cmd_id, const void *cmd_buf, size_t cmd_len,
  680. - void *resp_buf, size_t resp_len)
  681. -{
  682. - int ret;
  683. - struct scm_command *cmd;
  684. - struct scm_response *rsp;
  685. -
  686. - cmd = alloc_scm_command(cmd_len, resp_len);
  687. - if (!cmd)
  688. - return -ENOMEM;
  689. -
  690. - cmd->id = (svc_id << 10) | cmd_id;
  691. - if (cmd_buf)
  692. - memcpy(scm_get_command_buffer(cmd), cmd_buf, cmd_len);
  693. -
  694. - mutex_lock(&scm_lock);
  695. - ret = __scm_call(cmd);
  696. - mutex_unlock(&scm_lock);
  697. - if (ret)
  698. - goto out;
  699. -
  700. - rsp = scm_command_to_response(cmd);
  701. - do {
  702. - u32 start = (u32)rsp;
  703. - u32 end = (u32)scm_get_response_buffer(rsp) + resp_len;
  704. - start &= ~(CACHELINESIZE - 1);
  705. - while (start < end) {
  706. - asm ("mcr p15, 0, %0, c7, c6, 1" : : "r" (start)
  707. - : "memory");
  708. - start += CACHELINESIZE;
  709. - }
  710. - } while (!rsp->is_complete);
  711. -
  712. - if (resp_buf)
  713. - memcpy(resp_buf, scm_get_response_buffer(rsp), resp_len);
  714. -out:
  715. - free_scm_command(cmd);
  716. - return ret;
  717. -}
  718. -EXPORT_SYMBOL(scm_call);
  719. -
  720. -u32 scm_get_version(void)
  721. -{
  722. - int context_id;
  723. - static u32 version = -1;
  724. - register u32 r0 asm("r0");
  725. - register u32 r1 asm("r1");
  726. -
  727. - if (version != -1)
  728. - return version;
  729. -
  730. - mutex_lock(&scm_lock);
  731. -
  732. - r0 = 0x1 << 8;
  733. - r1 = (u32)&context_id;
  734. - do {
  735. - asm volatile(
  736. - __asmeq("%0", "r0")
  737. - __asmeq("%1", "r1")
  738. - __asmeq("%2", "r0")
  739. - __asmeq("%3", "r1")
  740. -#ifdef REQUIRES_SEC
  741. - ".arch_extension sec\n"
  742. -#endif
  743. - "smc #0 @ switch to secure world\n"
  744. - : "=r" (r0), "=r" (r1)
  745. - : "r" (r0), "r" (r1)
  746. - : "r2", "r3");
  747. - } while (r0 == SCM_INTERRUPTED);
  748. -
  749. - version = r1;
  750. - mutex_unlock(&scm_lock);
  751. -
  752. - return version;
  753. -}
  754. -EXPORT_SYMBOL(scm_get_version);
  755. --- a/arch/arm/mach-msm/scm.h
  756. +++ /dev/null
  757. @@ -1,25 +0,0 @@
  758. -/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
  759. - *
  760. - * This program is free software; you can redistribute it and/or modify
  761. - * it under the terms of the GNU General Public License version 2 and
  762. - * only version 2 as published by the Free Software Foundation.
  763. - *
  764. - * This program is distributed in the hope that it will be useful,
  765. - * but WITHOUT ANY WARRANTY; without even the implied warranty of
  766. - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  767. - * GNU General Public License for more details.
  768. - */
  769. -#ifndef __MACH_SCM_H
  770. -#define __MACH_SCM_H
  771. -
  772. -#define SCM_SVC_BOOT 0x1
  773. -#define SCM_SVC_PIL 0x2
  774. -
  775. -extern int scm_call(u32 svc_id, u32 cmd_id, const void *cmd_buf, size_t cmd_len,
  776. - void *resp_buf, size_t resp_len);
  777. -
  778. -#define SCM_VERSION(major, minor) (((major) << 16) | ((minor) & 0xFF))
  779. -
  780. -extern u32 scm_get_version(void);
  781. -
  782. -#endif
  783. --- /dev/null
  784. +++ b/arch/arm/mach-qcom/Kconfig
  785. @@ -0,0 +1,33 @@
  786. +config ARCH_QCOM
  787. + bool "Qualcomm Support" if ARCH_MULTI_V7
  788. + select ARCH_REQUIRE_GPIOLIB
  789. + select ARM_GIC
  790. + select CLKSRC_OF
  791. + select GENERIC_CLOCKEVENTS
  792. + select HAVE_SMP
  793. + select QCOM_SCM if SMP
  794. + help
  795. + Support for Qualcomm's devicetree based systems.
  796. +
  797. +if ARCH_QCOM
  798. +
  799. +menu "Qualcomm SoC Selection"
  800. +
  801. +config ARCH_MSM8X60
  802. + bool "Enable support for MSM8X60"
  803. + select CLKSRC_QCOM
  804. +
  805. +config ARCH_MSM8960
  806. + bool "Enable support for MSM8960"
  807. + select CLKSRC_QCOM
  808. +
  809. +config ARCH_MSM8974
  810. + bool "Enable support for MSM8974"
  811. + select HAVE_ARM_ARCH_TIMER
  812. +
  813. +endmenu
  814. +
  815. +config QCOM_SCM
  816. + bool
  817. +
  818. +endif
  819. --- /dev/null
  820. +++ b/arch/arm/mach-qcom/Makefile
  821. @@ -0,0 +1,5 @@
  822. +obj-y := board.o
  823. +obj-$(CONFIG_SMP) += platsmp.o
  824. +obj-$(CONFIG_QCOM_SCM) += scm.o scm-boot.o
  825. +
  826. +CFLAGS_scm.o :=$(call as-instr,.arch_extension sec,-DREQUIRES_SEC=1)
  827. --- /dev/null
  828. +++ b/arch/arm/mach-qcom/board.c
  829. @@ -0,0 +1,40 @@
  830. +/* Copyright (c) 2010-2014 The Linux Foundation. All rights reserved.
  831. + *
  832. + * This program is free software; you can redistribute it and/or modify
  833. + * it under the terms of the GNU General Public License version 2 and
  834. + * only version 2 as published by the Free Software Foundation.
  835. + *
  836. + * This program is distributed in the hope that it will be useful,
  837. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  838. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  839. + * GNU General Public License for more details.
  840. + */
  841. +
  842. +#include <linux/init.h>
  843. +#include <linux/of.h>
  844. +#include <linux/of_platform.h>
  845. +
  846. +#include <asm/mach/arch.h>
  847. +#include <asm/mach/map.h>
  848. +
  849. +extern struct smp_operations msm_smp_ops;
  850. +
  851. +static const char * const qcom_dt_match[] __initconst = {
  852. + "qcom,msm8660-surf",
  853. + "qcom,msm8960-cdp",
  854. + NULL
  855. +};
  856. +
  857. +static const char * const apq8074_dt_match[] __initconst = {
  858. + "qcom,apq8074-dragonboard",
  859. + NULL
  860. +};
  861. +
  862. +DT_MACHINE_START(QCOM_DT, "Qualcomm (Flattened Device Tree)")
  863. + .smp = smp_ops(msm_smp_ops),
  864. + .dt_compat = qcom_dt_match,
  865. +MACHINE_END
  866. +
  867. +DT_MACHINE_START(APQ_DT, "Qualcomm (Flattened Device Tree)")
  868. + .dt_compat = apq8074_dt_match,
  869. +MACHINE_END
  870. --- /dev/null
  871. +++ b/arch/arm/mach-qcom/platsmp.c
  872. @@ -0,0 +1,137 @@
  873. +/*
  874. + * Copyright (C) 2002 ARM Ltd.
  875. + * All Rights Reserved
  876. + * Copyright (c) 2010, Code Aurora Forum. All rights reserved.
  877. + * Copyright (c) 2014 The Linux Foundation. All rights reserved.
  878. + *
  879. + * This program is free software; you can redistribute it and/or modify
  880. + * it under the terms of the GNU General Public License version 2 as
  881. + * published by the Free Software Foundation.
  882. + */
  883. +
  884. +#include <linux/init.h>
  885. +#include <linux/errno.h>
  886. +#include <linux/delay.h>
  887. +#include <linux/device.h>
  888. +#include <linux/smp.h>
  889. +#include <linux/io.h>
  890. +
  891. +#include <asm/cputype.h>
  892. +#include <asm/smp_plat.h>
  893. +
  894. +#include "scm-boot.h"
  895. +
  896. +#define VDD_SC1_ARRAY_CLAMP_GFS_CTL 0x15A0
  897. +#define SCSS_CPU1CORE_RESET 0xD80
  898. +#define SCSS_DBG_STATUS_CORE_PWRDUP 0xE64
  899. +
  900. +extern void secondary_startup(void);
  901. +
  902. +static DEFINE_SPINLOCK(boot_lock);
  903. +
  904. +#ifdef CONFIG_HOTPLUG_CPU
  905. +static void __ref msm_cpu_die(unsigned int cpu)
  906. +{
  907. + wfi();
  908. +}
  909. +#endif
  910. +
  911. +static inline int get_core_count(void)
  912. +{
  913. + /* 1 + the PART[1:0] field of MIDR */
  914. + return ((read_cpuid_id() >> 4) & 3) + 1;
  915. +}
  916. +
  917. +static void msm_secondary_init(unsigned int cpu)
  918. +{
  919. + /*
  920. + * Synchronise with the boot thread.
  921. + */
  922. + spin_lock(&boot_lock);
  923. + spin_unlock(&boot_lock);
  924. +}
  925. +
  926. +static void prepare_cold_cpu(unsigned int cpu)
  927. +{
  928. + int ret;
  929. + ret = scm_set_boot_addr(virt_to_phys(secondary_startup),
  930. + SCM_FLAG_COLDBOOT_CPU1);
  931. + if (ret == 0) {
  932. + void __iomem *sc1_base_ptr;
  933. + sc1_base_ptr = ioremap_nocache(0x00902000, SZ_4K*2);
  934. + if (sc1_base_ptr) {
  935. + writel(0, sc1_base_ptr + VDD_SC1_ARRAY_CLAMP_GFS_CTL);
  936. + writel(0, sc1_base_ptr + SCSS_CPU1CORE_RESET);
  937. + writel(3, sc1_base_ptr + SCSS_DBG_STATUS_CORE_PWRDUP);
  938. + iounmap(sc1_base_ptr);
  939. + }
  940. + } else
  941. + printk(KERN_DEBUG "Failed to set secondary core boot "
  942. + "address\n");
  943. +}
  944. +
  945. +static int msm_boot_secondary(unsigned int cpu, struct task_struct *idle)
  946. +{
  947. + static int cold_boot_done;
  948. +
  949. + /* Only need to bring cpu out of reset this way once */
  950. + if (cold_boot_done == false) {
  951. + prepare_cold_cpu(cpu);
  952. + cold_boot_done = true;
  953. + }
  954. +
  955. + /*
  956. + * set synchronisation state between this boot processor
  957. + * and the secondary one
  958. + */
  959. + spin_lock(&boot_lock);
  960. +
  961. + /*
  962. + * Send the secondary CPU a soft interrupt, thereby causing
  963. + * the boot monitor to read the system wide flags register,
  964. + * and branch to the address found there.
  965. + */
  966. + arch_send_wakeup_ipi_mask(cpumask_of(cpu));
  967. +
  968. + /*
  969. + * now the secondary core is starting up let it run its
  970. + * calibrations, then wait for it to finish
  971. + */
  972. + spin_unlock(&boot_lock);
  973. +
  974. + return 0;
  975. +}
  976. +
  977. +/*
  978. + * Initialise the CPU possible map early - this describes the CPUs
  979. + * which may be present or become present in the system. The msm8x60
  980. + * does not support the ARM SCU, so just set the possible cpu mask to
  981. + * NR_CPUS.
  982. + */
  983. +static void __init msm_smp_init_cpus(void)
  984. +{
  985. + unsigned int i, ncores = get_core_count();
  986. +
  987. + if (ncores > nr_cpu_ids) {
  988. + pr_warn("SMP: %u cores greater than maximum (%u), clipping\n",
  989. + ncores, nr_cpu_ids);
  990. + ncores = nr_cpu_ids;
  991. + }
  992. +
  993. + for (i = 0; i < ncores; i++)
  994. + set_cpu_possible(i, true);
  995. +}
  996. +
  997. +static void __init msm_smp_prepare_cpus(unsigned int max_cpus)
  998. +{
  999. +}
  1000. +
  1001. +struct smp_operations msm_smp_ops __initdata = {
  1002. + .smp_init_cpus = msm_smp_init_cpus,
  1003. + .smp_prepare_cpus = msm_smp_prepare_cpus,
  1004. + .smp_secondary_init = msm_secondary_init,
  1005. + .smp_boot_secondary = msm_boot_secondary,
  1006. +#ifdef CONFIG_HOTPLUG_CPU
  1007. + .cpu_die = msm_cpu_die,
  1008. +#endif
  1009. +};
  1010. --- /dev/null
  1011. +++ b/arch/arm/mach-qcom/scm-boot.c
  1012. @@ -0,0 +1,39 @@
  1013. +/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
  1014. + *
  1015. + * This program is free software; you can redistribute it and/or modify
  1016. + * it under the terms of the GNU General Public License version 2 and
  1017. + * only version 2 as published by the Free Software Foundation.
  1018. + *
  1019. + * This program is distributed in the hope that it will be useful,
  1020. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  1021. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  1022. + * GNU General Public License for more details.
  1023. + *
  1024. + * You should have received a copy of the GNU General Public License
  1025. + * along with this program; if not, write to the Free Software
  1026. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  1027. + * 02110-1301, USA.
  1028. + */
  1029. +
  1030. +#include <linux/module.h>
  1031. +#include <linux/slab.h>
  1032. +
  1033. +#include "scm.h"
  1034. +#include "scm-boot.h"
  1035. +
  1036. +/*
  1037. + * Set the cold/warm boot address for one of the CPU cores.
  1038. + */
  1039. +int scm_set_boot_addr(phys_addr_t addr, int flags)
  1040. +{
  1041. + struct {
  1042. + unsigned int flags;
  1043. + phys_addr_t addr;
  1044. + } cmd;
  1045. +
  1046. + cmd.addr = addr;
  1047. + cmd.flags = flags;
  1048. + return scm_call(SCM_SVC_BOOT, SCM_BOOT_ADDR,
  1049. + &cmd, sizeof(cmd), NULL, 0);
  1050. +}
  1051. +EXPORT_SYMBOL(scm_set_boot_addr);
  1052. --- /dev/null
  1053. +++ b/arch/arm/mach-qcom/scm-boot.h
  1054. @@ -0,0 +1,22 @@
  1055. +/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
  1056. + *
  1057. + * This program is free software; you can redistribute it and/or modify
  1058. + * it under the terms of the GNU General Public License version 2 and
  1059. + * only version 2 as published by the Free Software Foundation.
  1060. + *
  1061. + * This program is distributed in the hope that it will be useful,
  1062. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  1063. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  1064. + * GNU General Public License for more details.
  1065. + */
  1066. +#ifndef __MACH_SCM_BOOT_H
  1067. +#define __MACH_SCM_BOOT_H
  1068. +
  1069. +#define SCM_BOOT_ADDR 0x1
  1070. +#define SCM_FLAG_COLDBOOT_CPU1 0x1
  1071. +#define SCM_FLAG_WARMBOOT_CPU1 0x2
  1072. +#define SCM_FLAG_WARMBOOT_CPU0 0x4
  1073. +
  1074. +int scm_set_boot_addr(phys_addr_t addr, int flags);
  1075. +
  1076. +#endif
  1077. --- /dev/null
  1078. +++ b/arch/arm/mach-qcom/scm.c
  1079. @@ -0,0 +1,299 @@
  1080. +/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
  1081. + *
  1082. + * This program is free software; you can redistribute it and/or modify
  1083. + * it under the terms of the GNU General Public License version 2 and
  1084. + * only version 2 as published by the Free Software Foundation.
  1085. + *
  1086. + * This program is distributed in the hope that it will be useful,
  1087. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  1088. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  1089. + * GNU General Public License for more details.
  1090. + *
  1091. + * You should have received a copy of the GNU General Public License
  1092. + * along with this program; if not, write to the Free Software
  1093. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  1094. + * 02110-1301, USA.
  1095. + */
  1096. +
  1097. +#include <linux/slab.h>
  1098. +#include <linux/io.h>
  1099. +#include <linux/module.h>
  1100. +#include <linux/mutex.h>
  1101. +#include <linux/errno.h>
  1102. +#include <linux/err.h>
  1103. +
  1104. +#include <asm/cacheflush.h>
  1105. +
  1106. +#include "scm.h"
  1107. +
  1108. +/* Cache line size for msm8x60 */
  1109. +#define CACHELINESIZE 32
  1110. +
  1111. +#define SCM_ENOMEM -5
  1112. +#define SCM_EOPNOTSUPP -4
  1113. +#define SCM_EINVAL_ADDR -3
  1114. +#define SCM_EINVAL_ARG -2
  1115. +#define SCM_ERROR -1
  1116. +#define SCM_INTERRUPTED 1
  1117. +
  1118. +static DEFINE_MUTEX(scm_lock);
  1119. +
  1120. +/**
  1121. + * struct scm_command - one SCM command buffer
  1122. + * @len: total available memory for command and response
  1123. + * @buf_offset: start of command buffer
  1124. + * @resp_hdr_offset: start of response buffer
  1125. + * @id: command to be executed
  1126. + * @buf: buffer returned from scm_get_command_buffer()
  1127. + *
  1128. + * An SCM command is laid out in memory as follows:
  1129. + *
  1130. + * ------------------- <--- struct scm_command
  1131. + * | command header |
  1132. + * ------------------- <--- scm_get_command_buffer()
  1133. + * | command buffer |
  1134. + * ------------------- <--- struct scm_response and
  1135. + * | response header | scm_command_to_response()
  1136. + * ------------------- <--- scm_get_response_buffer()
  1137. + * | response buffer |
  1138. + * -------------------
  1139. + *
  1140. + * There can be arbitrary padding between the headers and buffers so
  1141. + * you should always use the appropriate scm_get_*_buffer() routines
  1142. + * to access the buffers in a safe manner.
  1143. + */
  1144. +struct scm_command {
  1145. + u32 len;
  1146. + u32 buf_offset;
  1147. + u32 resp_hdr_offset;
  1148. + u32 id;
  1149. + u32 buf[0];
  1150. +};
  1151. +
  1152. +/**
  1153. + * struct scm_response - one SCM response buffer
  1154. + * @len: total available memory for response
  1155. + * @buf_offset: start of response data relative to start of scm_response
  1156. + * @is_complete: indicates if the command has finished processing
  1157. + */
  1158. +struct scm_response {
  1159. + u32 len;
  1160. + u32 buf_offset;
  1161. + u32 is_complete;
  1162. +};
  1163. +
  1164. +/**
  1165. + * alloc_scm_command() - Allocate an SCM command
  1166. + * @cmd_size: size of the command buffer
  1167. + * @resp_size: size of the response buffer
  1168. + *
  1169. + * Allocate an SCM command, including enough room for the command
  1170. + * and response headers as well as the command and response buffers.
  1171. + *
  1172. + * Returns a valid &scm_command on success or %NULL if the allocation fails.
  1173. + */
  1174. +static struct scm_command *alloc_scm_command(size_t cmd_size, size_t resp_size)
  1175. +{
  1176. + struct scm_command *cmd;
  1177. + size_t len = sizeof(*cmd) + sizeof(struct scm_response) + cmd_size +
  1178. + resp_size;
  1179. +
  1180. + cmd = kzalloc(PAGE_ALIGN(len), GFP_KERNEL);
  1181. + if (cmd) {
  1182. + cmd->len = len;
  1183. + cmd->buf_offset = offsetof(struct scm_command, buf);
  1184. + cmd->resp_hdr_offset = cmd->buf_offset + cmd_size;
  1185. + }
  1186. + return cmd;
  1187. +}
  1188. +
  1189. +/**
  1190. + * free_scm_command() - Free an SCM command
  1191. + * @cmd: command to free
  1192. + *
  1193. + * Free an SCM command.
  1194. + */
  1195. +static inline void free_scm_command(struct scm_command *cmd)
  1196. +{
  1197. + kfree(cmd);
  1198. +}
  1199. +
  1200. +/**
  1201. + * scm_command_to_response() - Get a pointer to a scm_response
  1202. + * @cmd: command
  1203. + *
  1204. + * Returns a pointer to a response for a command.
  1205. + */
  1206. +static inline struct scm_response *scm_command_to_response(
  1207. + const struct scm_command *cmd)
  1208. +{
  1209. + return (void *)cmd + cmd->resp_hdr_offset;
  1210. +}
  1211. +
  1212. +/**
  1213. + * scm_get_command_buffer() - Get a pointer to a command buffer
  1214. + * @cmd: command
  1215. + *
  1216. + * Returns a pointer to the command buffer of a command.
  1217. + */
  1218. +static inline void *scm_get_command_buffer(const struct scm_command *cmd)
  1219. +{
  1220. + return (void *)cmd->buf;
  1221. +}
  1222. +
  1223. +/**
  1224. + * scm_get_response_buffer() - Get a pointer to a response buffer
  1225. + * @rsp: response
  1226. + *
  1227. + * Returns a pointer to a response buffer of a response.
  1228. + */
  1229. +static inline void *scm_get_response_buffer(const struct scm_response *rsp)
  1230. +{
  1231. + return (void *)rsp + rsp->buf_offset;
  1232. +}
  1233. +
  1234. +static int scm_remap_error(int err)
  1235. +{
  1236. + switch (err) {
  1237. + case SCM_ERROR:
  1238. + return -EIO;
  1239. + case SCM_EINVAL_ADDR:
  1240. + case SCM_EINVAL_ARG:
  1241. + return -EINVAL;
  1242. + case SCM_EOPNOTSUPP:
  1243. + return -EOPNOTSUPP;
  1244. + case SCM_ENOMEM:
  1245. + return -ENOMEM;
  1246. + }
  1247. + return -EINVAL;
  1248. +}
  1249. +
  1250. +static u32 smc(u32 cmd_addr)
  1251. +{
  1252. + int context_id;
  1253. + register u32 r0 asm("r0") = 1;
  1254. + register u32 r1 asm("r1") = (u32)&context_id;
  1255. + register u32 r2 asm("r2") = cmd_addr;
  1256. + do {
  1257. + asm volatile(
  1258. + __asmeq("%0", "r0")
  1259. + __asmeq("%1", "r0")
  1260. + __asmeq("%2", "r1")
  1261. + __asmeq("%3", "r2")
  1262. +#ifdef REQUIRES_SEC
  1263. + ".arch_extension sec\n"
  1264. +#endif
  1265. + "smc #0 @ switch to secure world\n"
  1266. + : "=r" (r0)
  1267. + : "r" (r0), "r" (r1), "r" (r2)
  1268. + : "r3");
  1269. + } while (r0 == SCM_INTERRUPTED);
  1270. +
  1271. + return r0;
  1272. +}
  1273. +
  1274. +static int __scm_call(const struct scm_command *cmd)
  1275. +{
  1276. + int ret;
  1277. + u32 cmd_addr = virt_to_phys(cmd);
  1278. +
  1279. + /*
  1280. + * Flush the entire cache here so callers don't have to remember
  1281. + * to flush the cache when passing physical addresses to the secure
  1282. + * side in the buffer.
  1283. + */
  1284. + flush_cache_all();
  1285. + ret = smc(cmd_addr);
  1286. + if (ret < 0)
  1287. + ret = scm_remap_error(ret);
  1288. +
  1289. + return ret;
  1290. +}
  1291. +
  1292. +/**
  1293. + * scm_call() - Send an SCM command
  1294. + * @svc_id: service identifier
  1295. + * @cmd_id: command identifier
  1296. + * @cmd_buf: command buffer
  1297. + * @cmd_len: length of the command buffer
  1298. + * @resp_buf: response buffer
  1299. + * @resp_len: length of the response buffer
  1300. + *
  1301. + * Sends a command to the SCM and waits for the command to finish processing.
  1302. + */
  1303. +int scm_call(u32 svc_id, u32 cmd_id, const void *cmd_buf, size_t cmd_len,
  1304. + void *resp_buf, size_t resp_len)
  1305. +{
  1306. + int ret;
  1307. + struct scm_command *cmd;
  1308. + struct scm_response *rsp;
  1309. +
  1310. + cmd = alloc_scm_command(cmd_len, resp_len);
  1311. + if (!cmd)
  1312. + return -ENOMEM;
  1313. +
  1314. + cmd->id = (svc_id << 10) | cmd_id;
  1315. + if (cmd_buf)
  1316. + memcpy(scm_get_command_buffer(cmd), cmd_buf, cmd_len);
  1317. +
  1318. + mutex_lock(&scm_lock);
  1319. + ret = __scm_call(cmd);
  1320. + mutex_unlock(&scm_lock);
  1321. + if (ret)
  1322. + goto out;
  1323. +
  1324. + rsp = scm_command_to_response(cmd);
  1325. + do {
  1326. + u32 start = (u32)rsp;
  1327. + u32 end = (u32)scm_get_response_buffer(rsp) + resp_len;
  1328. + start &= ~(CACHELINESIZE - 1);
  1329. + while (start < end) {
  1330. + asm ("mcr p15, 0, %0, c7, c6, 1" : : "r" (start)
  1331. + : "memory");
  1332. + start += CACHELINESIZE;
  1333. + }
  1334. + } while (!rsp->is_complete);
  1335. +
  1336. + if (resp_buf)
  1337. + memcpy(resp_buf, scm_get_response_buffer(rsp), resp_len);
  1338. +out:
  1339. + free_scm_command(cmd);
  1340. + return ret;
  1341. +}
  1342. +EXPORT_SYMBOL(scm_call);
  1343. +
  1344. +u32 scm_get_version(void)
  1345. +{
  1346. + int context_id;
  1347. + static u32 version = -1;
  1348. + register u32 r0 asm("r0");
  1349. + register u32 r1 asm("r1");
  1350. +
  1351. + if (version != -1)
  1352. + return version;
  1353. +
  1354. + mutex_lock(&scm_lock);
  1355. +
  1356. + r0 = 0x1 << 8;
  1357. + r1 = (u32)&context_id;
  1358. + do {
  1359. + asm volatile(
  1360. + __asmeq("%0", "r0")
  1361. + __asmeq("%1", "r1")
  1362. + __asmeq("%2", "r0")
  1363. + __asmeq("%3", "r1")
  1364. +#ifdef REQUIRES_SEC
  1365. + ".arch_extension sec\n"
  1366. +#endif
  1367. + "smc #0 @ switch to secure world\n"
  1368. + : "=r" (r0), "=r" (r1)
  1369. + : "r" (r0), "r" (r1)
  1370. + : "r2", "r3");
  1371. + } while (r0 == SCM_INTERRUPTED);
  1372. +
  1373. + version = r1;
  1374. + mutex_unlock(&scm_lock);
  1375. +
  1376. + return version;
  1377. +}
  1378. +EXPORT_SYMBOL(scm_get_version);
  1379. --- /dev/null
  1380. +++ b/arch/arm/mach-qcom/scm.h
  1381. @@ -0,0 +1,25 @@
  1382. +/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
  1383. + *
  1384. + * This program is free software; you can redistribute it and/or modify
  1385. + * it under the terms of the GNU General Public License version 2 and
  1386. + * only version 2 as published by the Free Software Foundation.
  1387. + *
  1388. + * This program is distributed in the hope that it will be useful,
  1389. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  1390. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  1391. + * GNU General Public License for more details.
  1392. + */
  1393. +#ifndef __MACH_SCM_H
  1394. +#define __MACH_SCM_H
  1395. +
  1396. +#define SCM_SVC_BOOT 0x1
  1397. +#define SCM_SVC_PIL 0x2
  1398. +
  1399. +extern int scm_call(u32 svc_id, u32 cmd_id, const void *cmd_buf, size_t cmd_len,
  1400. + void *resp_buf, size_t resp_len);
  1401. +
  1402. +#define SCM_VERSION(major, minor) (((major) << 16) | ((minor) & 0xFF))
  1403. +
  1404. +extern u32 scm_get_version(void);
  1405. +
  1406. +#endif