Commit 14a43e69ed257a1fadadf9fea2c05adb1686419f

Authored by Benjamin Herrenschmidt
1 parent 817c21ad9a

powerpc/powernv: Basic support for OPAL

Add definition of OPAL interfaces along with  the wrappers to call
into OPAL runtime and the early device-tree parsing hook to locate
the OPAL runtime firmware.

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>

Showing 9 changed files with 691 additions and 5 deletions Side-by-side Diff

arch/powerpc/include/asm/firmware.h
... ... @@ -48,6 +48,8 @@
48 48 #define FW_FEATURE_CMO ASM_CONST(0x0000000002000000)
49 49 #define FW_FEATURE_VPHN ASM_CONST(0x0000000004000000)
50 50 #define FW_FEATURE_XCMO ASM_CONST(0x0000000008000000)
  51 +#define FW_FEATURE_OPAL ASM_CONST(0x0000000010000000)
  52 +#define FW_FEATURE_OPALv2 ASM_CONST(0x0000000020000000)
51 53  
52 54 #ifndef __ASSEMBLY__
53 55  
... ... @@ -65,6 +67,8 @@
65 67 FW_FEATURE_PSERIES_ALWAYS = 0,
66 68 FW_FEATURE_ISERIES_POSSIBLE = FW_FEATURE_ISERIES | FW_FEATURE_LPAR,
67 69 FW_FEATURE_ISERIES_ALWAYS = FW_FEATURE_ISERIES | FW_FEATURE_LPAR,
  70 + FW_FEATURE_POWERNV_POSSIBLE = FW_FEATURE_OPAL | FW_FEATURE_OPALv2,
  71 + FW_FEATURE_POWERNV_ALWAYS = 0,
68 72 FW_FEATURE_PS3_POSSIBLE = FW_FEATURE_LPAR | FW_FEATURE_PS3_LV1,
69 73 FW_FEATURE_PS3_ALWAYS = FW_FEATURE_LPAR | FW_FEATURE_PS3_LV1,
70 74 FW_FEATURE_CELLEB_POSSIBLE = FW_FEATURE_LPAR | FW_FEATURE_BEAT,
... ... @@ -78,6 +82,9 @@
78 82 #ifdef CONFIG_PPC_ISERIES
79 83 FW_FEATURE_ISERIES_POSSIBLE |
80 84 #endif
  85 +#ifdef CONFIG_PPC_POWERNV
  86 + FW_FEATURE_POWERNV_POSSIBLE |
  87 +#endif
81 88 #ifdef CONFIG_PPC_PS3
82 89 FW_FEATURE_PS3_POSSIBLE |
83 90 #endif
... ... @@ -94,6 +101,9 @@
94 101 #endif
95 102 #ifdef CONFIG_PPC_ISERIES
96 103 FW_FEATURE_ISERIES_ALWAYS &
  104 +#endif
  105 +#ifdef CONFIG_PPC_POWERNV
  106 + FW_FEATURE_POWERNV_ALWAYS &
97 107 #endif
98 108 #ifdef CONFIG_PPC_PS3
99 109 FW_FEATURE_PS3_ALWAYS &
arch/powerpc/include/asm/opal.h
... ... @@ -37,15 +37,395 @@
37 37  
38 38 extern long opal_do_takeover(struct opal_takeover_args *args);
39 39  
  40 +struct rtas_args;
40 41 extern int opal_enter_rtas(struct rtas_args *args,
41 42 unsigned long data,
42 43 unsigned long entry);
43 44  
44   -
45 45 #endif /* __ASSEMBLY__ */
46 46  
47 47 /****** OPAL APIs ******/
48 48  
  49 +/* Return codes */
  50 +#define OPAL_SUCCESS 0
  51 +#define OPAL_PARAMETER -1
  52 +#define OPAL_BUSY -2
  53 +#define OPAL_PARTIAL -3
  54 +#define OPAL_CONSTRAINED -4
  55 +#define OPAL_CLOSED -5
  56 +#define OPAL_HARDWARE -6
  57 +#define OPAL_UNSUPPORTED -7
  58 +#define OPAL_PERMISSION -8
  59 +#define OPAL_NO_MEM -9
  60 +#define OPAL_RESOURCE -10
  61 +#define OPAL_INTERNAL_ERROR -11
  62 +#define OPAL_BUSY_EVENT -12
  63 +#define OPAL_HARDWARE_FROZEN -13
  64 +
  65 +/* API Tokens (in r0) */
  66 +#define OPAL_CONSOLE_WRITE 1
  67 +#define OPAL_CONSOLE_READ 2
  68 +#define OPAL_RTC_READ 3
  69 +#define OPAL_RTC_WRITE 4
  70 +#define OPAL_CEC_POWER_DOWN 5
  71 +#define OPAL_CEC_REBOOT 6
  72 +#define OPAL_READ_NVRAM 7
  73 +#define OPAL_WRITE_NVRAM 8
  74 +#define OPAL_HANDLE_INTERRUPT 9
  75 +#define OPAL_POLL_EVENTS 10
  76 +#define OPAL_PCI_SET_HUB_TCE_MEMORY 11
  77 +#define OPAL_PCI_SET_PHB_TCE_MEMORY 12
  78 +#define OPAL_PCI_CONFIG_READ_BYTE 13
  79 +#define OPAL_PCI_CONFIG_READ_HALF_WORD 14
  80 +#define OPAL_PCI_CONFIG_READ_WORD 15
  81 +#define OPAL_PCI_CONFIG_WRITE_BYTE 16
  82 +#define OPAL_PCI_CONFIG_WRITE_HALF_WORD 17
  83 +#define OPAL_PCI_CONFIG_WRITE_WORD 18
  84 +#define OPAL_SET_XIVE 19
  85 +#define OPAL_GET_XIVE 20
  86 +#define OPAL_GET_COMPLETION_TOKEN_STATUS 21 /* obsolete */
  87 +#define OPAL_REGISTER_OPAL_EXCEPTION_HANDLER 22
  88 +#define OPAL_PCI_EEH_FREEZE_STATUS 23
  89 +#define OPAL_PCI_SHPC 24
  90 +#define OPAL_CONSOLE_WRITE_BUFFER_SPACE 25
  91 +#define OPAL_PCI_EEH_FREEZE_CLEAR 26
  92 +#define OPAL_PCI_PHB_MMIO_ENABLE 27
  93 +#define OPAL_PCI_SET_PHB_MEM_WINDOW 28
  94 +#define OPAL_PCI_MAP_PE_MMIO_WINDOW 29
  95 +#define OPAL_PCI_SET_PHB_TABLE_MEMORY 30
  96 +#define OPAL_PCI_SET_PE 31
  97 +#define OPAL_PCI_SET_PELTV 32
  98 +#define OPAL_PCI_SET_MVE 33
  99 +#define OPAL_PCI_SET_MVE_ENABLE 34
  100 +#define OPAL_PCI_GET_XIVE_REISSUE 35
  101 +#define OPAL_PCI_SET_XIVE_REISSUE 36
  102 +#define OPAL_PCI_SET_XIVE_PE 37
  103 +#define OPAL_GET_XIVE_SOURCE 38
  104 +#define OPAL_GET_MSI_32 39
  105 +#define OPAL_GET_MSI_64 40
  106 +#define OPAL_START_CPU 41
  107 +#define OPAL_QUERY_CPU_STATUS 42
  108 +#define OPAL_WRITE_OPPANEL 43
  109 +#define OPAL_PCI_MAP_PE_DMA_WINDOW 44
  110 +#define OPAL_PCI_MAP_PE_DMA_WINDOW_REAL 45
  111 +#define OPAL_PCI_RESET 49
  112 +
  113 +#ifndef __ASSEMBLY__
  114 +
  115 +/* Other enums */
  116 +enum OpalVendorApiTokens {
  117 + OPAL_START_VENDOR_API_RANGE = 1000, OPAL_END_VENDOR_API_RANGE = 1999
  118 +};
  119 +enum OpalFreezeState {
  120 + OPAL_EEH_STOPPED_NOT_FROZEN = 0,
  121 + OPAL_EEH_STOPPED_MMIO_FREEZE = 1,
  122 + OPAL_EEH_STOPPED_DMA_FREEZE = 2,
  123 + OPAL_EEH_STOPPED_MMIO_DMA_FREEZE = 3,
  124 + OPAL_EEH_STOPPED_RESET = 4,
  125 + OPAL_EEH_STOPPED_TEMP_UNAVAIL = 5,
  126 + OPAL_EEH_STOPPED_PERM_UNAVAIL = 6
  127 +};
  128 +enum OpalEehFreezeActionToken {
  129 + OPAL_EEH_ACTION_CLEAR_FREEZE_MMIO = 1,
  130 + OPAL_EEH_ACTION_CLEAR_FREEZE_DMA = 2,
  131 + OPAL_EEH_ACTION_CLEAR_FREEZE_ALL = 3
  132 +};
  133 +enum OpalPciStatusToken {
  134 + OPAL_EEH_PHB_NO_ERROR = 0,
  135 + OPAL_EEH_PHB_FATAL = 1,
  136 + OPAL_EEH_PHB_RECOVERABLE = 2,
  137 + OPAL_EEH_PHB_BUS_ERROR = 3,
  138 + OPAL_EEH_PCI_NO_DEVSEL = 4,
  139 + OPAL_EEH_PCI_TA = 5,
  140 + OPAL_EEH_PCIEX_UR = 6,
  141 + OPAL_EEH_PCIEX_CA = 7,
  142 + OPAL_EEH_PCI_MMIO_ERROR = 8,
  143 + OPAL_EEH_PCI_DMA_ERROR = 9
  144 +};
  145 +enum OpalShpcAction {
  146 + OPAL_SHPC_GET_LINK_STATE = 0,
  147 + OPAL_SHPC_GET_SLOT_STATE = 1
  148 +};
  149 +enum OpalShpcLinkState {
  150 + OPAL_SHPC_LINK_DOWN = 0,
  151 + OPAL_SHPC_LINK_UP = 1
  152 +};
  153 +enum OpalMmioWindowType {
  154 + OPAL_M32_WINDOW_TYPE = 1,
  155 + OPAL_M64_WINDOW_TYPE = 2,
  156 + OPAL_IO_WINDOW_TYPE = 3
  157 +};
  158 +enum OpalShpcSlotState {
  159 + OPAL_SHPC_DEV_NOT_PRESENT = 0,
  160 + OPAL_SHPC_DEV_PRESENT = 1
  161 +};
  162 +enum OpalExceptionHandler {
  163 + OPAL_MACHINE_CHECK_HANDLER = 1,
  164 + OPAL_HYPERVISOR_MAINTENANCE_HANDLER = 2,
  165 + OPAL_SOFTPATCH_HANDLER = 3
  166 +};
  167 +enum OpalPendingState {
  168 + OPAL_EVENT_OPAL_INTERNAL = 0x1,
  169 + OPAL_EVENT_NVRAM = 0x2,
  170 + OPAL_EVENT_RTC = 0x4,
  171 + OPAL_EVENT_CONSOLE_OUTPUT = 0x8,
  172 + OPAL_EVENT_CONSOLE_INPUT = 0x10
  173 +};
  174 +
  175 +/* Machine check related definitions */
  176 +enum OpalMCE_Version {
  177 + OpalMCE_V1 = 1,
  178 +};
  179 +
  180 +enum OpalMCE_Severity {
  181 + OpalMCE_SEV_NO_ERROR = 0,
  182 + OpalMCE_SEV_WARNING = 1,
  183 + OpalMCE_SEV_ERROR_SYNC = 2,
  184 + OpalMCE_SEV_FATAL = 3,
  185 +};
  186 +
  187 +enum OpalMCE_Disposition {
  188 + OpalMCE_DISPOSITION_RECOVERED = 0,
  189 + OpalMCE_DISPOSITION_NOT_RECOVERED = 1,
  190 +};
  191 +
  192 +enum OpalMCE_Initiator {
  193 + OpalMCE_INITIATOR_UNKNOWN = 0,
  194 + OpalMCE_INITIATOR_CPU = 1,
  195 +};
  196 +
  197 +enum OpalMCE_ErrorType {
  198 + OpalMCE_ERROR_TYPE_UNKNOWN = 0,
  199 + OpalMCE_ERROR_TYPE_UE = 1,
  200 + OpalMCE_ERROR_TYPE_SLB = 2,
  201 + OpalMCE_ERROR_TYPE_ERAT = 3,
  202 + OpalMCE_ERROR_TYPE_TLB = 4,
  203 +};
  204 +
  205 +enum OpalMCE_UeErrorType {
  206 + OpalMCE_UE_ERROR_INDETERMINATE = 0,
  207 + OpalMCE_UE_ERROR_IFETCH = 1,
  208 + OpalMCE_UE_ERROR_PAGE_TABLE_WALK_IFETCH = 2,
  209 + OpalMCE_UE_ERROR_LOAD_STORE = 3,
  210 + OpalMCE_UE_ERROR_PAGE_TABLE_WALK_LOAD_STORE = 4,
  211 +};
  212 +
  213 +enum OpalMCE_SlbErrorType {
  214 + OpalMCE_SLB_ERROR_INDETERMINATE = 0,
  215 + OpalMCE_SLB_ERROR_PARITY = 1,
  216 + OpalMCE_SLB_ERROR_MULTIHIT = 2,
  217 +};
  218 +
  219 +enum OpalMCE_EratErrorType {
  220 + OpalMCE_ERAT_ERROR_INDETERMINATE = 0,
  221 + OpalMCE_ERAT_ERROR_PARITY = 1,
  222 + OpalMCE_ERAT_ERROR_MULTIHIT = 2,
  223 +};
  224 +
  225 +enum OpalMCE_TlbErrorType {
  226 + OpalMCE_TLB_ERROR_INDETERMINATE = 0,
  227 + OpalMCE_TLB_ERROR_PARITY = 1,
  228 + OpalMCE_TLB_ERROR_MULTIHIT = 2,
  229 +};
  230 +
  231 +enum OpalThreadStatus {
  232 + OPAL_THREAD_INACTIVE = 0x0,
  233 + OPAL_THREAD_STARTED = 0x1
  234 +};
  235 +
  236 +enum OpalPciBusCompare {
  237 + OpalPciBusAny = 0, /* Any bus number match */
  238 + OpalPciBus3Bits = 2, /* Match top 3 bits of bus number */
  239 + OpalPciBus4Bits = 3, /* Match top 4 bits of bus number */
  240 + OpalPciBus5Bits = 4, /* Match top 5 bits of bus number */
  241 + OpalPciBus6Bits = 5, /* Match top 6 bits of bus number */
  242 + OpalPciBus7Bits = 6, /* Match top 7 bits of bus number */
  243 + OpalPciBusAll = 7, /* Match bus number exactly */
  244 +};
  245 +
  246 +enum OpalDeviceCompare {
  247 + OPAL_IGNORE_RID_DEVICE_NUMBER = 0,
  248 + OPAL_COMPARE_RID_DEVICE_NUMBER = 1
  249 +};
  250 +
  251 +enum OpalFuncCompare {
  252 + OPAL_IGNORE_RID_FUNCTION_NUMBER = 0,
  253 + OPAL_COMPARE_RID_FUNCTION_NUMBER = 1
  254 +};
  255 +
  256 +enum OpalPeAction {
  257 + OPAL_UNMAP_PE = 0,
  258 + OPAL_MAP_PE = 1
  259 +};
  260 +
  261 +enum OpalPciResetAndReinitScope {
  262 + OPAL_PHB_COMPLETE = 1, OPAL_PCI_LINK = 2, OPAL_PHB_ERROR = 3,
  263 + OPAL_PCI_HOT_RESET = 4, OPAL_PCI_FUNDAMENTAL_RESET = 5,
  264 + OPAL_PCI_IODA_RESET = 6,
  265 +};
  266 +
  267 +enum OpalPciResetState { OPAL_DEASSERT_RESET = 0, OPAL_ASSERT_RESET = 1 };
  268 +
  269 +struct opal_machine_check_event {
  270 + enum OpalMCE_Version version:8; /* 0x00 */
  271 + uint8_t in_use; /* 0x01 */
  272 + enum OpalMCE_Severity severity:8; /* 0x02 */
  273 + enum OpalMCE_Initiator initiator:8; /* 0x03 */
  274 + enum OpalMCE_ErrorType error_type:8; /* 0x04 */
  275 + enum OpalMCE_Disposition disposition:8; /* 0x05 */
  276 + uint8_t reserved_1[2]; /* 0x06 */
  277 + uint64_t gpr3; /* 0x08 */
  278 + uint64_t srr0; /* 0x10 */
  279 + uint64_t srr1; /* 0x18 */
  280 + union { /* 0x20 */
  281 + struct {
  282 + enum OpalMCE_UeErrorType ue_error_type:8;
  283 + uint8_t effective_address_provided;
  284 + uint8_t physical_address_provided;
  285 + uint8_t reserved_1[5];
  286 + uint64_t effective_address;
  287 + uint64_t physical_address;
  288 + uint8_t reserved_2[8];
  289 + } ue_error;
  290 +
  291 + struct {
  292 + enum OpalMCE_SlbErrorType slb_error_type:8;
  293 + uint8_t effective_address_provided;
  294 + uint8_t reserved_1[6];
  295 + uint64_t effective_address;
  296 + uint8_t reserved_2[16];
  297 + } slb_error;
  298 +
  299 + struct {
  300 + enum OpalMCE_EratErrorType erat_error_type:8;
  301 + uint8_t effective_address_provided;
  302 + uint8_t reserved_1[6];
  303 + uint64_t effective_address;
  304 + uint8_t reserved_2[16];
  305 + } erat_error;
  306 +
  307 + struct {
  308 + enum OpalMCE_TlbErrorType tlb_error_type:8;
  309 + uint8_t effective_address_provided;
  310 + uint8_t reserved_1[6];
  311 + uint64_t effective_address;
  312 + uint8_t reserved_2[16];
  313 + } tlb_error;
  314 + } u;
  315 +};
  316 +
  317 +typedef struct oppanel_line {
  318 + /* XXX */
  319 +} oppanel_line_t;
  320 +
  321 +/* API functions */
  322 +int64_t opal_console_write(int64_t term_number, int64_t *length,
  323 + const uint8_t *buffer);
  324 +int64_t opal_console_read(int64_t term_number, int64_t *length,
  325 + uint8_t *buffer);
  326 +int64_t opal_console_write_buffer_space(int64_t term_number,
  327 + int64_t *length);
  328 +int64_t opal_rtc_read(uint32_t *year_month_day,
  329 + uint64_t *hour_minute_second_millisecond);
  330 +int64_t opal_rtc_write(uint32_t year_month_day,
  331 + uint64_t hour_minute_second_millisecond);
  332 +int64_t opal_cec_power_down(uint64_t request);
  333 +int64_t opal_cec_reboot(void);
  334 +int64_t opal_read_nvram(uint64_t buffer, uint64_t size, uint64_t offset);
  335 +int64_t opal_write_nvram(uint64_t buffer, uint64_t size, uint64_t offset);
  336 +int64_t opal_handle_interrupt(uint64_t isn, uint64_t *outstanding_event_mask);
  337 +int64_t opal_poll_events(uint64_t *outstanding_event_mask);
  338 +int64_t opal_pci_set_hub_tce_memory(uint64_t hub_id, uint64_t tce_mem_addr,
  339 + uint64_t tce_mem_size);
  340 +int64_t opal_pci_set_phb_tce_memory(uint64_t phb_id, uint64_t tce_mem_addr,
  341 + uint64_t tce_mem_size);
  342 +int64_t opal_pci_config_read_byte(uint64_t phb_id, uint64_t bus_dev_func,
  343 + uint64_t offset, uint8_t *data);
  344 +int64_t opal_pci_config_read_half_word(uint64_t phb_id, uint64_t bus_dev_func,
  345 + uint64_t offset, uint16_t *data);
  346 +int64_t opal_pci_config_read_word(uint64_t phb_id, uint64_t bus_dev_func,
  347 + uint64_t offset, uint32_t *data);
  348 +int64_t opal_pci_config_write_byte(uint64_t phb_id, uint64_t bus_dev_func,
  349 + uint64_t offset, uint8_t data);
  350 +int64_t opal_pci_config_write_half_word(uint64_t phb_id, uint64_t bus_dev_func,
  351 + uint64_t offset, uint16_t data);
  352 +int64_t opal_pci_config_write_word(uint64_t phb_id, uint64_t bus_dev_func,
  353 + uint64_t offset, uint32_t data);
  354 +int64_t opal_set_xive(uint32_t isn, uint16_t server, uint8_t priority);
  355 +int64_t opal_get_xive(uint32_t isn, uint16_t *server, uint8_t *priority);
  356 +int64_t opal_register_exception_handler(uint64_t opal_exception,
  357 + uint64_t handler_address,
  358 + uint64_t glue_cache_line);
  359 +int64_t opal_pci_eeh_freeze_status(uint64_t phb_id, uint64_t pe_number,
  360 + uint8_t *freeze_state,
  361 + uint16_t *pci_error_type,
  362 + uint64_t *phb_status);
  363 +int64_t opal_pci_eeh_freeze_clear(uint64_t phb_id, uint64_t pe_number,
  364 + uint64_t eeh_action_token);
  365 +int64_t opal_pci_shpc(uint64_t phb_id, uint64_t shpc_action, uint8_t *state);
  366 +
  367 +
  368 +
  369 +int64_t opal_pci_phb_mmio_enable(uint64_t phb_id, uint16_t window_type,
  370 + uint16_t window_num, uint16_t enable);
  371 +int64_t opal_pci_set_phb_mem_window(uint64_t phb_id, uint16_t window_type,
  372 + uint16_t window_num,
  373 + uint64_t starting_real_address,
  374 + uint64_t starting_pci_address,
  375 + uint16_t segment_size);
  376 +int64_t opal_pci_map_pe_mmio_window(uint64_t phb_id, uint16_t pe_number,
  377 + uint16_t window_type, uint16_t window_num,
  378 + uint16_t segment_num);
  379 +int64_t opal_pci_set_phb_table_memory(uint64_t phb_id, uint64_t rtt_addr,
  380 + uint64_t ivt_addr, uint64_t ivt_len,
  381 + uint64_t reject_array_addr,
  382 + uint64_t peltv_addr);
  383 +int64_t opal_pci_set_pe(uint64_t phb_id, uint64_t pe_number, uint64_t bus_dev_func,
  384 + uint8_t bus_compare, uint8_t dev_compare, uint8_t func_compare,
  385 + uint8_t pe_action);
  386 +int64_t opal_pci_set_peltv(uint64_t phb_id, uint32_t parent_pe, uint32_t child_pe,
  387 + uint8_t state);
  388 +int64_t opal_pci_set_mve(uint64_t phb_id, uint32_t mve_number, uint32_t pe_number);
  389 +int64_t opal_pci_set_mve_enable(uint64_t phb_id, uint32_t mve_number,
  390 + uint32_t state);
  391 +int64_t opal_pci_get_xive_reissue(uint64_t phb_id, uint32_t xive_number,
  392 + uint8_t *p_bit, uint8_t *q_bit);
  393 +int64_t opal_pci_set_xive_reissue(uint64_t phb_id, uint32_t xive_number,
  394 + uint8_t p_bit, uint8_t q_bit);
  395 +int64_t opal_pci_set_xive_pe(uint64_t phb_id, uint32_t pe_number,
  396 + uint32_t xive_num);
  397 +int64_t opal_get_xive_source(uint64_t phb_id, uint32_t xive_num,
  398 + int32_t *interrupt_source_number);
  399 +int64_t opal_get_msi_32(uint64_t phb_id, uint32_t mve_number, uint32_t xive_num,
  400 + uint8_t msi_range, uint32_t *msi_address,
  401 + uint32_t *message_data);
  402 +int64_t opal_get_msi_64(uint64_t phb_id, uint32_t mve_number,
  403 + uint32_t xive_num, uint8_t msi_range,
  404 + uint64_t *msi_address, uint32_t *message_data);
  405 +int64_t opal_start_cpu(uint64_t thread_number, uint64_t start_address);
  406 +int64_t opal_query_cpu_status(uint64_t thread_number, uint8_t *thread_status);
  407 +int64_t opal_write_oppanel(oppanel_line_t *lines, uint64_t num_lines);
  408 +int64_t opal_pci_map_pe_dma_window(uint64_t phb_id, uint16_t pe_number, uint16_t window_id,
  409 + uint16_t tce_levels, uint64_t tce_table_addr,
  410 + uint64_t tce_table_size, uint64_t tce_page_size);
  411 +int64_t opal_pci_map_pe_dma_window_real(uint64_t phb_id, uint16_t pe_number,
  412 + uint16_t dma_window_number, uint64_t pci_start_addr,
  413 + uint64_t pci_mem_size);
  414 +int64_t opal_pci_reset(uint64_t phb_id, uint8_t reset_scope, uint8_t assert_state);
  415 +
  416 +/* Internal functions */
  417 +extern int early_init_dt_scan_opal(unsigned long node, const char *uname, int depth, void *data);
  418 +
  419 +extern int opal_get_chars(uint32_t vtermno, char *buf, int count);
  420 +extern int opal_put_chars(uint32_t vtermno, const char *buf, int total_len);
  421 +
  422 +extern void hvc_opal_init_early(void);
  423 +
  424 +/* Internal functions */
  425 +extern int early_init_dt_scan_opal(unsigned long node, const char *uname,
  426 + int depth, void *data);
  427 +
  428 +#endif /* __ASSEMBLY__ */
49 429  
50 430 #endif /* __OPAL_H */
arch/powerpc/kernel/prom.c
... ... @@ -54,6 +54,8 @@
54 54 #include <asm/pci-bridge.h>
55 55 #include <asm/phyp_dump.h>
56 56 #include <asm/kexec.h>
  57 +#include <asm/opal.h>
  58 +
57 59 #include <mm/mmu_decl.h>
58 60  
59 61 #ifdef DEBUG
... ... @@ -705,6 +707,11 @@
705 707 #ifdef CONFIG_PPC_RTAS
706 708 /* Some machines might need RTAS info for debugging, grab it now. */
707 709 of_scan_flat_dt(early_init_dt_scan_rtas, NULL);
  710 +#endif
  711 +
  712 +#ifdef CONFIG_PPC_POWERNV
  713 + /* Some machines might need OPAL info for debugging, grab it now. */
  714 + of_scan_flat_dt(early_init_dt_scan_opal, NULL);
708 715 #endif
709 716  
710 717 #ifdef CONFIG_PHYP_DUMP
arch/powerpc/platforms/powernv/Kconfig
1 1 config PPC_POWERNV
2 2 depends on PPC64 && PPC_BOOK3S
3 3 bool "IBM PowerNV (Non-Virtualized) platform support"
4   - select PPC_RTAS
5 4 select PPC_NATIVE
6 5 select PPC_XICS
7 6 select PPC_ICP_NATIVE
8   - select PPC_ICS_RTAS
9 7 select PPC_P7_NAP
10 8 select PPC_PCI_CHOICE if EMBEDDED
11 9 default y
  10 +
  11 +config PPC_POWERNV_RTAS
  12 + depends on PPC_POWERNV
  13 + bool "Support for RTAS based PowerNV platforms such as BML"
  14 + default y
  15 + select PPC_ICS_RTAS
  16 + select PPC_RTAS
arch/powerpc/platforms/powernv/Makefile
1   -obj-y += setup.o opal-takeover.o
  1 +obj-y += setup.o opal-takeover.o opal-wrappers.o opal.o
2 2 obj-$(CONFIG_SMP) += smp.o
arch/powerpc/platforms/powernv/opal-wrappers.S
  1 +/*
  2 + * PowerNV OPAL API wrappers
  3 + *
  4 + * Copyright 2011 IBM Corp.
  5 + *
  6 + * This program is free software; you can redistribute it and/or
  7 + * modify it under the terms of the GNU General Public License
  8 + * as published by the Free Software Foundation; either version
  9 + * 2 of the License, or (at your option) any later version.
  10 + */
  11 +
  12 +#include <asm/ppc_asm.h>
  13 +#include <asm/hvcall.h>
  14 +#include <asm/asm-offsets.h>
  15 +#include <asm/opal.h>
  16 +
  17 +/* TODO:
  18 + *
  19 + * - Trace irqs in/off (needs saving/restoring all args, argh...)
  20 + * - Get r11 feed up by Dave so I can have better register usage
  21 + */
  22 +#define OPAL_CALL(name, token) \
  23 + _GLOBAL(name); \
  24 + mflr r0; \
  25 + mfcr r12; \
  26 + std r0,16(r1); \
  27 + std r12,8(r1); \
  28 + std r1,PACAR1(r13); \
  29 + li r0,0; \
  30 + mfmsr r12; \
  31 + ori r0,r0,MSR_EE; \
  32 + std r12,PACASAVEDMSR(r13); \
  33 + andc r12,r12,r0; \
  34 + mtmsrd r12,1; \
  35 + LOAD_REG_ADDR(r0,.opal_return); \
  36 + mtlr r0; \
  37 + li r0,MSR_DR|MSR_IR; \
  38 + andc r12,r12,r0; \
  39 + li r0,token; \
  40 + mtspr SPRN_HSRR1,r12; \
  41 + LOAD_REG_ADDR(r11,opal); \
  42 + ld r12,8(r11); \
  43 + ld r2,0(r11); \
  44 + mtspr SPRN_HSRR0,r12; \
  45 + hrfid
  46 +
  47 +_STATIC(opal_return)
  48 + ld r2,PACATOC(r13);
  49 + ld r4,8(r1);
  50 + ld r5,16(r1);
  51 + ld r6,PACASAVEDMSR(r13);
  52 + mtspr SPRN_SRR0,r5;
  53 + mtspr SPRN_SRR1,r6;
  54 + mtcr r4;
  55 + rfid
  56 +
  57 +OPAL_CALL(opal_console_write, OPAL_CONSOLE_WRITE);
  58 +OPAL_CALL(opal_console_read, OPAL_CONSOLE_READ);
  59 +OPAL_CALL(opal_console_write_buffer_space, OPAL_CONSOLE_WRITE_BUFFER_SPACE);
  60 +OPAL_CALL(opal_rtc_read, OPAL_RTC_READ);
  61 +OPAL_CALL(opal_rtc_write, OPAL_RTC_WRITE);
  62 +OPAL_CALL(opal_cec_power_down, OPAL_CEC_POWER_DOWN);
  63 +OPAL_CALL(opal_cec_reboot, OPAL_CEC_REBOOT);
  64 +OPAL_CALL(opal_read_nvram, OPAL_READ_NVRAM);
  65 +OPAL_CALL(opal_write_nvram, OPAL_WRITE_NVRAM);
  66 +OPAL_CALL(opal_handle_interrupt, OPAL_HANDLE_INTERRUPT);
  67 +OPAL_CALL(opal_poll_events, OPAL_POLL_EVENTS);
  68 +OPAL_CALL(opal_pci_set_hub_tce_memory, OPAL_PCI_SET_HUB_TCE_MEMORY);
  69 +OPAL_CALL(opal_pci_set_phb_tce_memory, OPAL_PCI_SET_PHB_TCE_MEMORY);
  70 +OPAL_CALL(opal_pci_config_read_byte, OPAL_PCI_CONFIG_READ_BYTE);
  71 +OPAL_CALL(opal_pci_config_read_half_word, OPAL_PCI_CONFIG_READ_HALF_WORD);
  72 +OPAL_CALL(opal_pci_config_read_word, OPAL_PCI_CONFIG_READ_WORD);
  73 +OPAL_CALL(opal_pci_config_write_byte, OPAL_PCI_CONFIG_WRITE_BYTE);
  74 +OPAL_CALL(opal_pci_config_write_half_word, OPAL_PCI_CONFIG_WRITE_HALF_WORD);
  75 +OPAL_CALL(opal_pci_config_write_word, OPAL_PCI_CONFIG_WRITE_WORD);
  76 +OPAL_CALL(opal_set_xive, OPAL_SET_XIVE);
  77 +OPAL_CALL(opal_get_xive, OPAL_GET_XIVE);
  78 +OPAL_CALL(opal_register_exception_handler, OPAL_REGISTER_OPAL_EXCEPTION_HANDLER);
  79 +OPAL_CALL(opal_pci_eeh_freeze_status, OPAL_PCI_EEH_FREEZE_STATUS);
  80 +OPAL_CALL(opal_pci_eeh_freeze_clear, OPAL_PCI_EEH_FREEZE_CLEAR);
  81 +OPAL_CALL(opal_pci_shpc, OPAL_PCI_SHPC);
  82 +OPAL_CALL(opal_pci_phb_mmio_enable, OPAL_PCI_PHB_MMIO_ENABLE);
  83 +OPAL_CALL(opal_pci_set_phb_mem_window, OPAL_PCI_SET_PHB_MEM_WINDOW);
  84 +OPAL_CALL(opal_pci_map_pe_mmio_window, OPAL_PCI_MAP_PE_MMIO_WINDOW);
  85 +OPAL_CALL(opal_pci_set_phb_table_memory, OPAL_PCI_SET_PHB_TABLE_MEMORY);
  86 +OPAL_CALL(opal_pci_set_pe, OPAL_PCI_SET_PE);
  87 +OPAL_CALL(opal_pci_set_peltv, OPAL_PCI_SET_PELTV);
  88 +OPAL_CALL(opal_pci_set_mve, OPAL_PCI_SET_MVE);
  89 +OPAL_CALL(opal_pci_set_mve_enable, OPAL_PCI_SET_MVE_ENABLE);
  90 +OPAL_CALL(opal_pci_get_xive_reissue, OPAL_PCI_GET_XIVE_REISSUE);
  91 +OPAL_CALL(opal_pci_set_xive_reissue, OPAL_PCI_SET_XIVE_REISSUE);
  92 +OPAL_CALL(opal_pci_set_xive_pe, OPAL_PCI_SET_XIVE_PE);
  93 +OPAL_CALL(opal_get_xive_source, OPAL_GET_XIVE_SOURCE);
  94 +OPAL_CALL(opal_get_msi_32, OPAL_GET_MSI_32);
  95 +OPAL_CALL(opal_get_msi_64, OPAL_GET_MSI_64);
  96 +OPAL_CALL(opal_start_cpu, OPAL_START_CPU);
  97 +OPAL_CALL(opal_query_cpu_status, OPAL_QUERY_CPU_STATUS);
  98 +OPAL_CALL(opal_write_oppanel, OPAL_WRITE_OPPANEL);
  99 +OPAL_CALL(opal_pci_map_pe_dma_window, OPAL_PCI_MAP_PE_DMA_WINDOW);
  100 +OPAL_CALL(opal_pci_map_pe_dma_window_real, OPAL_PCI_MAP_PE_DMA_WINDOW_REAL);
  101 +OPAL_CALL(opal_pci_reset, OPAL_PCI_RESET);
arch/powerpc/platforms/powernv/opal.c
  1 +/*
  2 + * PowerNV OPAL high level interfaces
  3 + *
  4 + * Copyright 2011 IBM Corp.
  5 + *
  6 + * This program is free software; you can redistribute it and/or
  7 + * modify it under the terms of the GNU General Public License
  8 + * as published by the Free Software Foundation; either version
  9 + * 2 of the License, or (at your option) any later version.
  10 + */
  11 +
  12 +#undef DEBUG
  13 +
  14 +#include <linux/types.h>
  15 +#include <linux/of.h>
  16 +#include <linux/of_platform.h>
  17 +#include <asm/opal.h>
  18 +#include <asm/firmware.h>
  19 +
  20 +#include "powernv.h"
  21 +
  22 +struct opal {
  23 + u64 base;
  24 + u64 entry;
  25 +} opal;
  26 +
  27 +static struct device_node *opal_node;
  28 +static DEFINE_SPINLOCK(opal_write_lock);
  29 +
  30 +int __init early_init_dt_scan_opal(unsigned long node,
  31 + const char *uname, int depth, void *data)
  32 +{
  33 + const void *basep, *entryp;
  34 + unsigned long basesz, entrysz;
  35 +
  36 + if (depth != 1 || strcmp(uname, "ibm,opal") != 0)
  37 + return 0;
  38 +
  39 + basep = of_get_flat_dt_prop(node, "opal-base-address", &basesz);
  40 + entryp = of_get_flat_dt_prop(node, "opal-entry-address", &entrysz);
  41 +
  42 + if (!basep || !entryp)
  43 + return 1;
  44 +
  45 + opal.base = of_read_number(basep, basesz/4);
  46 + opal.entry = of_read_number(entryp, entrysz/4);
  47 +
  48 + pr_debug("OPAL Base = 0x%llx (basep=%p basesz=%ld)\n",
  49 + opal.base, basep, basesz);
  50 + pr_debug("OPAL Entry = 0x%llx (entryp=%p basesz=%ld)\n",
  51 + opal.entry, entryp, entrysz);
  52 +
  53 + powerpc_firmware_features |= FW_FEATURE_OPAL;
  54 + if (of_flat_dt_is_compatible(node, "ibm,opal-v2")) {
  55 + powerpc_firmware_features |= FW_FEATURE_OPALv2;
  56 + printk("OPAL V2 detected !\n");
  57 + } else {
  58 + printk("OPAL V1 detected !\n");
  59 + }
  60 +
  61 + return 1;
  62 +}
  63 +
  64 +int opal_get_chars(uint32_t vtermno, char *buf, int count)
  65 +{
  66 + s64 len, rc;
  67 + u64 evt;
  68 +
  69 + if (!opal.entry)
  70 + return 0;
  71 + opal_poll_events(&evt);
  72 + if ((evt & OPAL_EVENT_CONSOLE_INPUT) == 0)
  73 + return 0;
  74 + len = count;
  75 + rc = opal_console_read(vtermno, &len, buf);
  76 + if (rc == OPAL_SUCCESS)
  77 + return len;
  78 + return 0;
  79 +}
  80 +
  81 +int opal_put_chars(uint32_t vtermno, const char *data, int total_len)
  82 +{
  83 + int written = 0;
  84 + s64 len, rc = OPAL_BUSY;
  85 + unsigned long flags;
  86 + u64 evt;
  87 +
  88 + if (!opal.entry)
  89 + return 0;
  90 +
  91 + /* We want put_chars to be atomic to avoid mangling of hvsi
  92 + * packets. To do that, we first test for room and return
  93 + * -EAGAIN if there isn't enough
  94 + */
  95 + spin_lock_irqsave(&opal_write_lock, flags);
  96 + rc = opal_console_write_buffer_space(vtermno, &len);
  97 + if (rc || len < total_len) {
  98 + spin_unlock_irqrestore(&opal_write_lock, flags);
  99 + /* Closed -> drop characters */
  100 + if (rc)
  101 + return total_len;
  102 + opal_poll_events(&evt);
  103 + return -EAGAIN;
  104 + }
  105 +
  106 + /* We still try to handle partial completions, though they
  107 + * should no longer happen.
  108 + */
  109 + while(total_len > 0 && (rc == OPAL_BUSY ||
  110 + rc == OPAL_BUSY_EVENT || rc == OPAL_SUCCESS)) {
  111 + len = total_len;
  112 + rc = opal_console_write(vtermno, &len, data);
  113 + if (rc == OPAL_SUCCESS) {
  114 + total_len -= len;
  115 + data += len;
  116 + written += len;
  117 + }
  118 + /* This is a bit nasty but we need that for the console to
  119 + * flush when there aren't any interrupts. We will clean
  120 + * things a bit later to limit that to synchronous path
  121 + * such as the kernel console and xmon/udbg
  122 + */
  123 + do
  124 + opal_poll_events(&evt);
  125 + while(rc == OPAL_SUCCESS && (evt & OPAL_EVENT_CONSOLE_OUTPUT));
  126 + }
  127 + spin_unlock_irqrestore(&opal_write_lock, flags);
  128 + return written;
  129 +}
  130 +
  131 +static int __init opal_init(void)
  132 +{
  133 + struct device_node *np, *consoles;
  134 +
  135 + opal_node = of_find_node_by_path("/ibm,opal");
  136 + if (!opal_node) {
  137 + pr_warn("opal: Node not found\n");
  138 + return -ENODEV;
  139 + }
  140 + if (firmware_has_feature(FW_FEATURE_OPALv2))
  141 + consoles = of_find_node_by_path("/ibm,opal/consoles");
  142 + else
  143 + consoles = of_node_get(opal_node);
  144 +
  145 + /* Register serial ports */
  146 + for_each_child_of_node(consoles, np) {
  147 + if (strcmp(np->name, "serial"))
  148 + continue;
  149 + of_platform_device_create(np, NULL, NULL);
  150 + }
  151 + of_node_put(consoles);
  152 + return 0;
  153 +}
  154 +subsys_initcall(opal_init);
arch/powerpc/platforms/powernv/setup.c
... ... @@ -74,6 +74,12 @@
74 74 if (root)
75 75 model = of_get_property(root, "model", NULL);
76 76 seq_printf(m, "machine\t\t: PowerNV %s\n", model);
  77 + if (firmware_has_feature(FW_FEATURE_OPALv2))
  78 + seq_printf(m, "firmware\t: OPAL v2\n");
  79 + else if (firmware_has_feature(FW_FEATURE_OPAL))
  80 + seq_printf(m, "firmware\t: OPAL v1\n");
  81 + else
  82 + seq_printf(m, "firmware\t: BML\n");
77 83 of_node_put(root);
78 84 }
79 85  
arch/powerpc/platforms/powernv/smp.c
... ... @@ -30,6 +30,7 @@
30 30 #include <asm/vdso_datapage.h>
31 31 #include <asm/cputhreads.h>
32 32 #include <asm/xics.h>
  33 +#include <asm/opal.h>
33 34  
34 35 #include "powernv.h"
35 36  
... ... @@ -62,6 +63,28 @@
62 63 return 1;
63 64 }
64 65  
  66 +int __devinit pnv_smp_kick_cpu(int nr)
  67 +{
  68 + unsigned int pcpu = get_hard_smp_processor_id(nr);
  69 + unsigned long start_here = __pa(*((unsigned long *)
  70 + generic_secondary_smp_init));
  71 + long rc;
  72 +
  73 + BUG_ON(nr < 0 || nr >= NR_CPUS);
  74 +
  75 + /* On OPAL v2 the CPU are still spinning inside OPAL itself,
  76 + * get them back now
  77 + */
  78 + if (firmware_has_feature(FW_FEATURE_OPALv2)) {
  79 + pr_devel("OPAL: Starting CPU %d (HW 0x%x)...\n", nr, pcpu);
  80 + rc = opal_start_cpu(pcpu, start_here);
  81 + if (rc != OPAL_SUCCESS)
  82 + pr_warn("OPAL Error %ld starting CPU %d\n",
  83 + rc, nr);
  84 + }
  85 + return smp_generic_kick_cpu(nr);
  86 +}
  87 +
65 88 #ifdef CONFIG_HOTPLUG_CPU
66 89  
67 90 static int pnv_smp_cpu_disable(void)
... ... @@ -127,7 +150,7 @@
127 150 .message_pass = smp_muxed_ipi_message_pass,
128 151 .cause_ipi = NULL, /* Filled at runtime by xics_smp_probe() */
129 152 .probe = xics_smp_probe,
130   - .kick_cpu = smp_generic_kick_cpu,
  153 + .kick_cpu = pnv_smp_kick_cpu,
131 154 .setup_cpu = pnv_smp_setup_cpu,
132 155 .cpu_bootable = pnv_smp_cpu_bootable,
133 156 #ifdef CONFIG_HOTPLUG_CPU